2025-03-18 08:46:50 +08:00

345 lines
18 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
from django.contrib.auth.models import AbstractUser
from django.db import models
import hashlib
from utils.models import CoreModel, table_prefix
#自定义
GENDER_CHOICES = (
(0, "未知"),
(1, ""),
(2, ""),
)
class Users(AbstractUser, CoreModel):
IDENTITY_CHOICES = (
(0, "超级管理员"),
(1, "系统管理员"),
(2, "前端用户"),
)
username = models.CharField(max_length=50, unique=True, db_index=True, verbose_name='用户账号', help_text="用户账号")
email = models.EmailField(max_length=60, verbose_name="邮箱", null=True, blank=True, help_text="邮箱")
mobile = models.CharField(max_length=30,verbose_name="电话", null=True, blank=True, help_text="电话")
avatar = models.CharField(max_length=200,verbose_name="头像", null=True, blank=True, help_text="头像")
name = models.CharField(max_length=40, verbose_name="姓名", help_text="姓名")
nickname = models.CharField(max_length=100, help_text="用户昵称", verbose_name="用户昵称",default="")
gender = models.SmallIntegerField(choices=GENDER_CHOICES, verbose_name="性别", null=True, blank=True, help_text="性别")
post = models.ManyToManyField(to='Post', verbose_name='关联岗位', db_constraint=False, help_text="关联岗位")
role = models.ManyToManyField(to='Role', verbose_name='关联角色', db_constraint=False, help_text="关联角色")#这个就是保留跨表查询的便利(双下划线跨表查询```),但是不用约束字段了,一般公司都用false,这样就省的报错,因为没有了约束(Field字段对象,既约束,又建立表与表之间的关系
dept = models.ForeignKey(to='Dept', verbose_name='所属部门', on_delete=models.PROTECT, db_constraint=False, null=True,blank=True, help_text="关联部门")
# 自定义
identity = models.SmallIntegerField(choices=IDENTITY_CHOICES, verbose_name="身份标识", null=True, blank=True, default=2,help_text="身份标识")
balance = models.DecimalField(max_digits=10, decimal_places=2, default=0, verbose_name='钱包余额') # 钱包余额
# vipid = models.CharField(max_length=100, unique=True, help_text="会员id", verbose_name="会员id", null=True, blank=True)
is_delete = models.BooleanField(default=False, verbose_name="是否逻辑删除", help_text="是否逻辑删除")
class Meta:
db_table = table_prefix + "users"
verbose_name = '用户表'
verbose_name_plural = verbose_name
ordering = ('-create_datetime',)
def __str__(self):
return self.username
class Post(CoreModel):
name = models.CharField(null=False, max_length=64, verbose_name="岗位名称", help_text="岗位名称")
code = models.CharField(max_length=32, verbose_name="岗位编码", help_text="岗位编码")
sort = models.IntegerField(default=1, verbose_name="岗位顺序", help_text="岗位顺序")
STATUS_CHOICES = (
(0, "离职"),
(1, "在职"),
)
status = models.IntegerField(choices=STATUS_CHOICES, default=1, verbose_name="岗位状态", help_text="岗位状态")
class Meta:
db_table = table_prefix + "post"
verbose_name = '岗位表'
verbose_name_plural = verbose_name
ordering = ('sort',)
def __str__(self):
return self.name
class Role(CoreModel):
name = models.CharField(max_length=64, verbose_name="角色名称", help_text="角色名称")
key = models.CharField(max_length=64, verbose_name="权限字符", help_text="权限字符")
sort = models.IntegerField(default=1, verbose_name="角色顺序", help_text="角色顺序")
STATUS_CHOICES = (
(0, "禁用"),
(1, "启用"),
)
status = models.SmallIntegerField(choices=STATUS_CHOICES, default=1, verbose_name="角色状态", help_text="角色状态")
ADMIN_CHOICES = (
(0, ""),
(1, ""),
)
admin = models.SmallIntegerField(choices=ADMIN_CHOICES, default=0, verbose_name="是否为admin", help_text="是否为admin")
DATASCOPE_CHOICES = (
(0, "仅本人数据权限"),
(1, "本部门数据权限"),
(2, "本部门及以下数据权限"),
(3, "全部数据权限"),
(4, "自定义数据权限"),
)
data_range = models.SmallIntegerField(default=0, choices=DATASCOPE_CHOICES, verbose_name="数据权限范围", help_text="数据权限范围")
remark = models.TextField(verbose_name="备注", help_text="备注", null=True, blank=True)
dept = models.ManyToManyField(to='Dept', verbose_name='数据权限-关联部门', db_constraint=False, help_text="数据权限-关联部门")#自定义数据权限时即data_range=4时会用到可以关联多个部门
menu = models.ManyToManyField(to='Menu', verbose_name='关联菜单', db_constraint=False, help_text="关联菜单")
permission = models.ManyToManyField(to='MenuButton', verbose_name='关联菜单的接口按钮', db_constraint=False,
help_text="关联菜单的接口按钮")
class Meta:
db_table = table_prefix + 'role'
verbose_name = '角色表'
verbose_name_plural = verbose_name
ordering = ('sort',)
def __str__(self):
return self.name
class RoleMenuDataRange(CoreModel):
"""
角色菜单数据授权(与角色里的数据授权区别:角色里的数据授权属于全局数据授权,角色菜单数据授权属于针对具体菜单的单独控制,过滤先后顺序:全局数据授权-->角色菜单数据授权)
"""
DATASCOPE_CHOICES = (
(0, "仅本人数据权限"),
(1, "本部门数据权限"),
(2, "本部门及以下数据权限"),
(3, "全部数据权限"),
(4, "自定义数据权限"),
(5, "同全局数据权限"),
)
role = models.ForeignKey(to='Role',related_name="lyrolemenu", verbose_name='关联角色', db_constraint=False, help_text="关联角色",on_delete=models.CASCADE)
data_range = models.SmallIntegerField(default=5, choices=DATASCOPE_CHOICES, verbose_name="数据权限范围", help_text="数据权限范围")
dept = models.ManyToManyField(to='Dept', verbose_name='数据权限-关联部门', db_constraint=False, help_text="数据权限-关联部门")#自定义数据权限时即data_range=4时会用到可以关联多个部门
menu = models.ForeignKey(to='Menu', verbose_name='关联菜单', db_constraint=False, help_text="关联菜单",on_delete=models.CASCADE)
class Meta:
db_table = table_prefix + 'role_menu_datarange'
verbose_name = '角色菜单数据授权'
verbose_name_plural = verbose_name
ordering = ('create_datetime',)
class Dept(CoreModel):
name = models.CharField(max_length=64, verbose_name="部门名称", help_text="部门名称")
sort = models.IntegerField(default=1, verbose_name="显示排序", help_text="显示排序")
owner = models.CharField(max_length=32, verbose_name="负责人", null=True, blank=True, help_text="负责人")
phone = models.CharField(max_length=32, verbose_name="联系电话", null=True, blank=True, help_text="联系电话")
email = models.EmailField(max_length=32, verbose_name="邮箱", null=True, blank=True, help_text="邮箱")
STATUS_CHOICES = (
(0, "禁用"),
(1, "启用"),
)
status = models.SmallIntegerField(choices=STATUS_CHOICES, default=1, verbose_name="部门状态", null=True, blank=True,
help_text="部门状态")
parent = models.ForeignKey(to='Dept', on_delete=models.CASCADE, default=False, verbose_name="上级部门",
db_constraint=False, null=True, blank=True, help_text="上级部门")
class Meta:
db_table = table_prefix + "dept"
verbose_name = '部门表'
verbose_name_plural = verbose_name
ordering = ('sort','create_datetime')
def __str__(self):
return self.name
class Button(CoreModel):
name = models.CharField(max_length=64, verbose_name="权限名称", help_text="权限名称")
value = models.CharField(max_length=64, verbose_name="权限值", help_text="权限值")
class Meta:
db_table = table_prefix + "button"
verbose_name = '权限标识表'
verbose_name_plural = verbose_name
ordering = ('-name',)
class Menu(CoreModel):
parent = models.ForeignKey(to='Menu', on_delete=models.CASCADE, verbose_name="上级菜单", null=True, blank=True,
db_constraint=False, help_text="上级菜单")
icon = models.CharField(max_length=64, verbose_name="菜单图标", null=True, blank=True, help_text="菜单图标")
name = models.CharField(max_length=64, verbose_name="菜单名称", help_text="菜单名称")
sort = models.IntegerField(default=1, verbose_name="显示排序", null=True, blank=True, help_text="显示排序")
ISLINK_CHOICES = (
(0, ""),
(1, ""),
)
is_link = models.SmallIntegerField(choices=ISLINK_CHOICES, default=0, verbose_name="是否外链", help_text="是否外链")
web_path = models.CharField(max_length=128, verbose_name="路由地址", null=True, blank=True, help_text="路由地址")
component = models.CharField(max_length=128, verbose_name="组件地址", null=True, blank=True, help_text="组件地址")
component_name = models.CharField(max_length=50, verbose_name="组件名称", null=True, blank=True, help_text="组件名称")
STATUS_CHOICES = (
(0, "禁用"),
(1, "启用"),
)
status = models.SmallIntegerField(choices=STATUS_CHOICES, default=1, verbose_name="菜单状态", help_text="菜单状态")
isautopm_CHOICES=(
(0,'不自动创建'),
(1,"自动创建")
)
isautopm = models.SmallIntegerField(choices=isautopm_CHOICES, default=1, verbose_name="自动创建按钮权限", help_text="自动创建按钮权限")
CACHE_CHOICES = (
(0, '禁用'),
(1, "启用")
)
cache = models.SmallIntegerField(choices=CACHE_CHOICES, default=0, verbose_name="是否页面缓存", help_text="是否页面缓存")
VISIBLE_CHOICES=(
(0,'不可见'),
(1,"可见")
)
visible = models.SmallIntegerField(choices=VISIBLE_CHOICES, default=1, verbose_name="侧边栏中是否显示", help_text="侧边栏中是否显示")
class Meta:
db_table = table_prefix + "menu"
verbose_name = '菜单表'
verbose_name_plural = verbose_name
ordering = ('sort',)
class MenuButton(CoreModel):
menu = models.ForeignKey(to="Menu", db_constraint=False, related_name="menuPermission", on_delete=models.CASCADE,
verbose_name="关联菜单", help_text='关联菜单')
name = models.CharField(max_length=64, verbose_name="名称", help_text="名称")
value = models.CharField(max_length=64, verbose_name="权限值", help_text="权限值")
api = models.CharField(max_length=64, verbose_name="接口地址", help_text="接口地址")
METHOD_CHOICES = (
(0, "GET"),
(1, "POST"),
(2, "PUT"),
(3, "DELETE"),
)
method = models.SmallIntegerField(default=0, verbose_name="接口请求方法", null=True, blank=True, help_text="接口请求方法")
class Meta:
db_table = table_prefix + "menu_button"
verbose_name = '菜单权限表'
verbose_name_plural = verbose_name
ordering = ('-name',)
class Dictionary(CoreModel):
label = models.CharField(max_length=100, blank=True, null=True, verbose_name="字典名称", help_text="字典名称")
value = models.CharField(max_length=200, blank=True, null=True, verbose_name="字典编号", help_text="字典编号/实际值")
status = models.BooleanField(default=True, verbose_name="状态", help_text="状态")
sort = models.IntegerField(default=1, verbose_name="显示排序", null=True, blank=True, help_text="显示排序")
parent = models.ForeignKey(to="self",related_name="sublist",db_constraint=False,on_delete=models.PROTECT,blank=True,null=True,verbose_name="父级",help_text="父级",)
remark = models.CharField(max_length=255, blank=True, null=True, verbose_name="备注", help_text="备注")
class Meta:
db_table = table_prefix + 'dictionary'
verbose_name = "字典表"
verbose_name_plural = verbose_name
ordering = ('sort',)
class AppVersion(CoreModel):
"""
APP版本管理
"""
TYPE_CHOICES = (
('ANDROID', "ANDROID"),
('IOS', "IOS"),
)
name = models.CharField(max_length=100, verbose_name="版本名称", default="")
version = models.CharField(max_length=60, verbose_name="版本号", default="")
type = models.CharField(choices=TYPE_CHOICES, verbose_name="类型",max_length=60,default="ANDROID")
content = models.TextField(verbose_name="更新内容", default="")
update_date = models.DateTimeField(auto_now=True, null=True, blank=True, help_text="发布更新时间", verbose_name="发布更新时间")
download_url = models.CharField(max_length=255, verbose_name="下载地址", default="")
isforce = models.BooleanField(default=False ,verbose_name="是否强制更新")
class Meta:
db_table = table_prefix + 'appversion'
verbose_name = "App版本"
verbose_name_plural = verbose_name
ordering = ('-create_datetime',)
class OperationLog(CoreModel):
request_modular = models.CharField(max_length=64, verbose_name="请求模块", null=True, blank=True, help_text="请求模块")
request_path = models.TextField(verbose_name="请求地址", null=True, blank=True, help_text="请求地址")
request_body = models.TextField(verbose_name="请求参数", null=True, blank=True, help_text="请求参数")
request_method = models.CharField(max_length=8, verbose_name="请求方式", null=True, blank=True, help_text="请求方式")
request_msg = models.TextField(verbose_name="操作说明", null=True, blank=True, help_text="操作说明")
request_ip = models.CharField(max_length=32, verbose_name="请求ip地址", null=True, blank=True, help_text="请求ip地址")
request_browser = models.CharField(max_length=64, verbose_name="请求浏览器", null=True, blank=True, help_text="请求浏览器")
response_code = models.CharField(max_length=32, verbose_name="响应状态码", null=True, blank=True, help_text="响应状态码")
request_os = models.CharField(max_length=64, verbose_name="操作系统", null=True, blank=True, help_text="操作系统")
json_result = models.TextField(verbose_name="返回信息", null=True, blank=True, help_text="返回信息")
status = models.BooleanField(default=False, verbose_name="响应状态", help_text="响应状态")
ip_area = models.CharField(max_length=100, verbose_name="IP归属地", null=True, blank=True, help_text="IP归属地")
class Meta:
db_table = table_prefix + 'operation_log'
verbose_name = '操作日志'
verbose_name_plural = verbose_name
ordering = ('-create_datetime',)
class LoginLog(CoreModel):
LOGIN_TYPE_CHOICES = (
(1, '后台登录'),
)
username = models.CharField(max_length=32, verbose_name="登录用户名", null=True, blank=True, help_text="登录用户名")
ip = models.CharField(max_length=32, verbose_name="登录ip", null=True, blank=True, help_text="登录ip")
agent = models.CharField(max_length=1500,verbose_name="agent信息", null=True, blank=True, help_text="agent信息")
browser = models.CharField(max_length=200, verbose_name="浏览器名", null=True, blank=True, help_text="浏览器名")
os = models.CharField(max_length=150, verbose_name="操作系统", null=True, blank=True, help_text="操作系统")
login_type = models.IntegerField(default=1, choices=LOGIN_TYPE_CHOICES, verbose_name="登录类型", help_text="登录类型")
class Meta:
db_table = table_prefix + 'login_log'
verbose_name = '登录日志'
verbose_name_plural = verbose_name
ordering = ('-create_datetime',)
class FileGroup(CoreModel):
name = models.CharField(max_length=50, null=True, blank=True, verbose_name="名称", help_text="名称")
sort = models.IntegerField(default=1, verbose_name="显示排序", null=True, blank=True, help_text="显示排序")
parent = models.ForeignKey('self', on_delete=models.SET_NULL, related_name='gsubs', null=True, blank=True,db_constraint=False, verbose_name='父级')#外键链接自己
class Meta:
db_table = table_prefix + "sys_files_group"
verbose_name = "文件分组"
verbose_name_plural = verbose_name
ordering = ("-create_datetime",)
def media_file_name(ins, filename):
h = ins.md5sum
basename, ext = os.path.splitext(filename)
return os.path.join("lyzfiles", h[:1], h[1:2], h + ext.lower())
class FileManage(CoreModel):
group = models.ForeignKey(FileGroup, verbose_name='所属分组', on_delete=models.SET_NULL, db_constraint=False, null=True,blank=True, help_text="关联部门")
name = models.CharField(max_length=200, null=True, blank=True, verbose_name="名称", help_text="名称")
url = models.FileField(upload_to=media_file_name, null=True, blank=True)
file_url = models.CharField(max_length=255, blank=True, verbose_name="文件地址", help_text="文件地址")
location = models.CharField(max_length=100, default='local', blank=True, verbose_name="存储位置", help_text="存储位置")
mime_type = models.CharField(max_length=100, blank=True, verbose_name="Mime类型", help_text="Mime类型")
size = models.CharField(max_length=36, blank=True, verbose_name="文件大小", help_text="文件大小")
md5sum = models.CharField(max_length=36, blank=True, verbose_name="文件md5", help_text="文件md5")
def save(self, *args, **kwargs):
if not self.md5sum:
md5 = hashlib.md5()
for chunk in self.url.chunks():
md5.update(chunk)
self.md5sum = md5.hexdigest()
if not self.size:
self.size = self.url.size
if not self.file_url:
url = media_file_name(self, self.name)
self.file_url = f'media/{url}'
super(FileManage, self).save(*args, **kwargs)
class Meta:
db_table = table_prefix + "sys_files"
verbose_name = "文件管理"
verbose_name_plural = verbose_name
ordering = ("-create_datetime",)