Files
vue-fastapi-admin/app/models/admin.py
T
2026-06-25 17:41:06 +08:00

297 lines
10 KiB
Python

from tortoise import fields
from tortoise import fields as Fields
from app.schemas.menus import MenuType
from .base import BaseModel, TimestampMixin
from .enums import MethodType
class User(BaseModel, TimestampMixin):
username = fields.CharField(max_length=20, unique=True, description="用户名称", index=True)
alias = fields.CharField(max_length=30, null=True, description="姓名", index=True)
email = fields.CharField(max_length=255, unique=True, description="邮箱", index=True)
phone = fields.CharField(max_length=20, null=True, description="电话", index=True)
password = fields.CharField(max_length=128, null=True, description="密码")
is_active = fields.BooleanField(default=True, description="是否激活", index=True)
is_superuser = fields.BooleanField(default=False, description="是否为超级管理员", index=True)
last_login = fields.DatetimeField(null=True, description="最后登录时间", index=True)
roles = fields.ManyToManyField("models.Role", related_name="user_roles")
dept_id = fields.IntField(null=True, description="部门ID", index=True)
class Meta:
table = "user"
class Role(BaseModel, TimestampMixin):
name = fields.CharField(max_length=20, unique=True, description="角色名称", index=True)
desc = fields.CharField(max_length=500, null=True, description="角色描述")
menus = fields.ManyToManyField("models.Menu", related_name="role_menus")
apis = fields.ManyToManyField("models.Api", related_name="role_apis")
class Meta:
table = "role"
class Api(BaseModel, TimestampMixin):
path = fields.CharField(max_length=100, description="API路径", index=True)
method = fields.CharEnumField(MethodType, description="请求方法", index=True)
summary = fields.CharField(max_length=500, description="请求简介", index=True)
tags = fields.CharField(max_length=100, description="API标签", index=True)
class Meta:
table = "api"
class Menu(BaseModel, TimestampMixin):
name = fields.CharField(max_length=20, description="菜单名称", index=True)
remark = fields.JSONField(null=True, description="保留字段")
menu_type = fields.CharEnumField(MenuType, null=True, description="菜单类型")
icon = fields.CharField(max_length=100, null=True, description="菜单图标")
path = fields.CharField(max_length=100, description="菜单路径", index=True)
order = fields.IntField(default=0, description="排序", index=True)
parent_id = fields.IntField(default=0, description="父菜单ID", index=True)
is_hidden = fields.BooleanField(default=False, description="是否隐藏")
component = fields.CharField(max_length=100, description="组件")
keepalive = fields.BooleanField(default=True, description="存活")
redirect = fields.CharField(max_length=100, null=True, description="重定向")
class Meta:
table = "menu"
class Dept(BaseModel, TimestampMixin):
name = fields.CharField(max_length=20, unique=True, description="部门名称", index=True)
desc = fields.CharField(max_length=500, null=True, description="备注")
is_deleted = fields.BooleanField(default=False, description="软删除标记", index=True)
order = fields.IntField(default=0, description="排序", index=True)
parent_id = fields.IntField(default=0, max_length=10, description="父部门ID", index=True)
class Meta:
table = "dept"
class DeptClosure(BaseModel, TimestampMixin):
ancestor = fields.IntField(description="父代", index=True)
descendant = fields.IntField(description="子代", index=True)
level = fields.IntField(default=0, description="深度", index=True)
class AuditLog(BaseModel, TimestampMixin):
user_id = fields.IntField(description="用户ID", index=True)
username = fields.CharField(max_length=64, default="", description="用户名称", index=True)
module = fields.CharField(max_length=64, default="", description="功能模块", index=True)
summary = fields.CharField(max_length=128, default="", description="请求描述", index=True)
method = fields.CharField(max_length=10, default="", description="请求方法", index=True)
path = fields.CharField(max_length=255, default="", description="请求路径", index=True)
status = fields.IntField(default=-1, description="状态码", index=True)
response_time = fields.IntField(default=0, description="响应时间(单位ms)", index=True)
request_args = fields.JSONField(null=True, description="请求参数")
response_body = fields.JSONField(null=True, description="返回数据")
class Codegen(BaseModel, TimestampMixin):
"""
{
"name": "user",
"author": "Ly997",
"description": "系统用户管理",
"version": "1.0.0",
"fields": [
{
"name": "id",
"type": "Long",
"primary_key": true,
"description": "用户ID",
"required": true,
"editable": true,
"listable": true,
"detailable": true,
"sortable": true,
"filterable": true,
"filter_operator": "equal",
"display_type": "text"
},
{
"name": "username",
"type": "String",
"length": 50,
"description": "用户名",
"required": true,
"unique": true,
"validations": [
{
"type": "min_length",
"value": 4
},
{
"type": "max_length",
"value": 20
}
],
"editable": true,
"listable": true,
"detailable": true,
"sortable": true,
"filterable": true,
"filter_operator": "equal",
"display_type": "text"
},
{
"name": "email",
"type": "String",
"description": "电子邮箱",
"required": true,
"validations": [
{
"type": "email"
}
],
"editable": true,
"listable": true,
"detailable": true,
"sortable": true,
"filterable": true,
"filter_operator": "equal",
"display_type": "text"
},
{
"name": "password_hash",
"type": "String",
"description": "密码哈希",
"required": true,
"secret": true,
"editable": true,
"listable": true,
"detailable": true,
"sortable": true,
"filterable": true,
"filter_operator": "equal",
"display_type": "text"
},
{
"name": "is_active",
"type": "Boolean",
"description": "是否激活",
"default": true,
"editable": true,
"listable": true,
"detailable": true,
"sortable": true,
"filterable": true,
"filter_operator": "equal",
"display_type": "text"
},
{
"name": "created_at",
"type": "DateTime",
"description": "创建时间",
"auto_now_add": true,
"editable": true,
"listable": true,
"detailable": true,
"sortable": true,
"filterable": true,
"filter_operator": "equal",
"display_type": "text"
},
{
"name": "updated_at",
"type": "DateTime",
"description": "更新时间",
"auto_now": true,
"editable": true,
"listable": true,
"detailable": true,
"sortable": true,
"filterable": true,
"filter_operator": "equal",
"display_type": "text"
}
],
"relations": [
{
"name": "roles",
"type": "many-to-many",
"target": "role",
"through": "user_roles",
"description": "用户角色关联"
},
{
"name": "posts",
"type": "one-to-many",
"target": "post",
"description": "用户发表的文章"
}
],
"api": {
"operations": [
"create",
"read",
"update",
"delete",
"list"
],
"base_path": "/users",
"auth_required": true,
"permissions": {
"create": [
"admin",
"manager"
],
"delete": [
"admin"
]
}
},
"menu": {
"label": "用户管理",
"icon": "user",
"order": 10,
"submenu": [
{
"label": "用户列表",
"path": "/users",
"icon": "list"
},
{
"label": "角色管理",
"path": "/roles"
}
]
}
} """
name = Fields.CharField(max_length=64, description="名称", index=True)
author = Fields.CharField(max_length=64, description="作者", index=True)
description = Fields.CharField(max_length=500, description="描述")
version = Fields.CharField(max_length=64, description="版本", index=True)
fields = Fields.JSONField(description="字段")
relations = Fields.JSONField(description="关系")
api = Fields.JSONField(description="API", null=True)
menu = Fields.JSONField(description="菜单", null=True)
class Meta:
table = "codegen"
async def dumps(self, output_type='pydantic'):
from app.schemas.codegen import BaseCodegen
obj_dict = await self.to_dict()
# print('type(obj_dict["fields"])', type(obj_dict["fields"]))
# print('type(obj_dict["relations"])', type(obj_dict["relations"]))
# print('type(obj_dict["api"])', type(obj_dict["api"]))
# obj_dict['fields'] = json.loads(obj_dict['fields'])
# obj_dict['relations'] = json.loads(obj_dict['relations'])
# obj_dict['api'] = json.loads(obj_dict['api'])
# obj_dict['menu'] = json.loads(obj_dict['menu'])
if output_type == 'pydantic': return BaseCodegen(**obj_dict)
else : return obj_dict
class Datasource(BaseModel, TimestampMixin):
tableName = Fields.CharField(max_length=32, description="名称", index=True)
tableComment = Fields.CharField(max_length=64, description="注释", index=True)
class Meta:
table = "datasource"