From 5364a5536ad0c75f1c4d06cacdbff1b53e729e82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BC=BA?= <1206709430@qq.com> Date: Mon, 10 Apr 2023 21:46:59 +0800 Subject: [PATCH 01/33] =?UTF-8?q?=E6=96=B0=E5=8A=9F=E8=83=BD:=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E9=85=8D=E7=BD=AEENVIRONMENT=E7=8E=AF=E5=A2=83?= =?UTF-8?q?=E5=8F=98=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/conf/env.example.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/conf/env.example.py b/backend/conf/env.example.py index 181d963..9ff3bcf 100644 --- a/backend/conf/env.example.py +++ b/backend/conf/env.example.py @@ -42,7 +42,7 @@ LOGIN_NO_CAPTCHA_AUTH = True # ================================================= # # ****************** 其他 配置 ******************* # # ================================================= # - +ENVIRONMENT = "local" # 环境,test 测试环境;prod线上环境;local本地环境 ALLOWED_HOSTS = ["*"] # 系统配置存放位置:redis/memory(默认) DISPATCH_DB_TYPE = 'redis' From 10c414ab8a1ed8cf5fefcaeffacafb5a5255943a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8C=BF=E5=B0=8F=E5=A4=A9?= <1638245306@qq.com> Date: Mon, 10 Apr 2023 21:59:37 +0800 Subject: [PATCH 02/33] =?UTF-8?q?bug=E4=BF=AE=E5=A4=8D:=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/views/system/config/components/formContent.vue | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/web/src/views/system/config/components/formContent.vue b/web/src/views/system/config/components/formContent.vue index c4ce14c..d7ee18e 100644 --- a/web/src/views/system/config/components/formContent.vue +++ b/web/src/views/system/config/components/formContent.vue @@ -331,6 +331,7 @@ export default { const form = JSON.parse(JSON.stringify(this.form)) const keys = Object.keys(form) const values = Object.values(form) + let submitForm = Object.assign([],this.formList) for (const index in this.formList) { const item = this.formList[index] // eslint-disable-next-line camelcase @@ -347,7 +348,7 @@ export default { child.parent = parentId child.id = null } - this.formList.push(child) + submitForm.push(child) } // 必填项的判断 for (const arr of item.rule) { @@ -380,7 +381,7 @@ export default { that.$refs.form.validate((valid) => { if (valid) { api.saveContent(this.options.id, - this.formList).then(res => { + submitForm).then(res => { this.$message.success('保存成功') this.refreshView() }) @@ -397,14 +398,13 @@ export default { const tableLength = tableData.length if (tableLength === 0) { const { row } = $table.insert() - console.log(row) } else { const errMap = await $table.validate().catch(errMap => errMap) if (errMap) { this.$message.error('校验不通过!') } else { const { row } = $table.insert() - console.log(row) + } } }, @@ -450,7 +450,7 @@ export default { if (!uploadImgKey || uploadImgKey === '') { that.form[imgKey] = [] } - // console.log(len) + const dict = { name: name, url: util.baseURL() + url From 5f2758c937aa56f11f6091358d790c31dee79a70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BC=BA?= <1206709430@qq.com> Date: Mon, 10 Apr 2023 23:30:35 +0800 Subject: [PATCH 03/33] =?UTF-8?q?perf:=20=E2=9A=A1=20=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E5=AD=97=E7=AC=A6=E9=95=BF=E5=BA=A6=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/application/settings.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/application/settings.py b/backend/application/settings.py index 6946d38..24b9887 100644 --- a/backend/application/settings.py +++ b/backend/application/settings.py @@ -412,10 +412,10 @@ PLUGINS_URL_PATTERNS = [] # ********** 一键导入插件配置开始 ********** # 例如: # from dvadmin_upgrade_center.settings import * # 升级中心 -# from dvadmin_celery.settings import * # celery 异步任务 -# from dvadmin_sms.settings import * # 短信服务 -# from dvadmin_third.settings import * # 扫码登录 -# from dvadmin_uniapp.settings import * # UniApp后端 +from dvadmin_celery.settings import * # celery 异步任务 +from dvadmin_sms.settings import * # 短信服务 +from dvadmin_third.settings import * # 扫码登录 +from dvadmin_uniapp.settings import * # UniApp后端 # from dvadmin_ak_sk.settings import * # 秘钥管理管理 # from dvadmin_tenants.settings import * # 租户管理 # ... From 03455ba9d047c9b7b9722de18e6d9b11e02c977a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BC=BA?= <1206709430@qq.com> Date: Thu, 13 Apr 2023 11:56:20 +0800 Subject: [PATCH 04/33] =?UTF-8?q?fix:=20=F0=9F=90=9B=20celery=20=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E4=B8=8D=E6=98=BE=E7=A4=BA=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/application/settings.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/backend/application/settings.py b/backend/application/settings.py index 24b9887..ddc8bc1 100644 --- a/backend/application/settings.py +++ b/backend/application/settings.py @@ -255,21 +255,11 @@ LOGGING = { "level": "INFO", "propagate": False, }, - 'celery': { - 'handlers': ["console", "error", "file"], - 'propagate': False, - 'level': "INFO" - }, 'django.db.backends': { 'handlers': ["console", "error", "file"], 'propagate': False, 'level': "INFO" }, - 'django.request': { - 'handlers': ["console", "error", "file"], - 'propagate': False, - 'level': "DEBUG" - }, "uvicorn.error": { "level": "INFO", "handlers": ["console", "error", "file"], From d31d9fc3cae3752b9f86309ff6377646a13e572d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BC=BA?= <1206709430@qq.com> Date: Fri, 14 Apr 2023 17:26:30 +0800 Subject: [PATCH 05/33] =?UTF-8?q?=E4=BC=98=E5=8C=96=EF=BC=9A=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E9=95=BF=E5=BA=A6=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/application/dispatch.py | 19 +++- backend/dvadmin/system/models.py | 117 +++++++++++++++-------- backend/dvadmin/system/views/login.py | 1 + backend/dvadmin/utils/models.py | 132 ++++++++++++++++++++++++-- backend/dvadmin/utils/request_util.py | 3 +- 5 files changed, 224 insertions(+), 48 deletions(-) diff --git a/backend/application/dispatch.py b/backend/application/dispatch.py index 5f65137..101b3ab 100644 --- a/backend/application/dispatch.py +++ b/backend/application/dispatch.py @@ -3,6 +3,7 @@ from django.conf import settings from django.db import connection from django.core.cache import cache +from dvadmin.utils.validator import CustomValidationError dispatch_db_type = getattr(settings, 'DISPATCH_DB_TYPE', 'memory') # redis @@ -159,7 +160,7 @@ def get_dictionary_config(schema_name=None): init_dictionary_data = cache.get(f"init_dictionary") if not init_dictionary_data: refresh_dictionary() - return cache.get(f"init_dictionary") or {} + return cache.get(f"init_dictionary") or {} if not settings.DICTIONARY_CONFIG: refresh_dictionary() if is_tenants_mode(): @@ -243,6 +244,22 @@ def get_system_config_values(key, schema_name=None): return system_config.get(key) +def get_system_config_values_to_dict(key, schema_name=None): + """ + 获取系统配置数据并转换为字典 **仅限于数组类型系统配置 + :param key: 对应系统配置的key值(字典编号) + :param schema_name: 对应系统配置的租户schema_name值 + :return: + """ + values_dict = {} + config_values = get_system_config_values(key, schema_name) + if not isinstance(config_values, list): + raise CustomValidationError("该方式仅限于数组类型系统配置") + for ele in get_system_config_values(key, schema_name): + values_dict[ele.get('key')] = ele.get('value') + return values_dict + + def get_system_config_label(key, name, schema_name=None): """ 获取获取系统配置label值 diff --git a/backend/dvadmin/system/models.py b/backend/dvadmin/system/models.py index 2326c83..c9a7db5 100644 --- a/backend/dvadmin/system/models.py +++ b/backend/dvadmin/system/models.py @@ -13,8 +13,11 @@ STATUS_CHOICES = ( ) -class Users(CoreModel,AbstractUser): - username = models.CharField(max_length=150, unique=True, db_index=True, verbose_name="用户账号", help_text="用户账号") +class Users(CoreModel, AbstractUser): + username = models.CharField(max_length=150, unique=True, db_index=True, verbose_name="用户账号", + help_text="用户账号") + employee_no = models.CharField(max_length=150, unique=True, db_index=True, null=True, blank=True, + verbose_name="工号", help_text="工号") email = models.EmailField(max_length=255, verbose_name="邮箱", null=True, blank=True, help_text="邮箱") mobile = models.CharField(max_length=255, verbose_name="电话", null=True, blank=True, help_text="电话") avatar = models.CharField(max_length=255, verbose_name="头像", null=True, blank=True, help_text="头像") @@ -34,8 +37,10 @@ class Users(CoreModel,AbstractUser): user_type = models.IntegerField( choices=USER_TYPE, default=0, verbose_name="用户类型", null=True, blank=True, help_text="用户类型" ) - post = models.ManyToManyField(to="Post",blank=True, verbose_name="关联岗位", db_constraint=False, help_text="关联岗位") - role = models.ManyToManyField(to="Role", blank=True,verbose_name="关联角色", db_constraint=False, help_text="关联角色") + post = models.ManyToManyField(to="Post", blank=True, verbose_name="关联岗位", db_constraint=False, + help_text="关联岗位") + role = models.ManyToManyField(to="Role", blank=True, verbose_name="关联角色", db_constraint=False, + help_text="关联角色") dept = models.ForeignKey( to="Dept", verbose_name="所属部门", @@ -45,7 +50,8 @@ class Users(CoreModel,AbstractUser): blank=True, help_text="关联部门", ) - last_token = models.CharField(max_length=255,null=True,blank=True, verbose_name="最后一次登录Token", help_text="最后一次登录Token") + last_token = models.CharField(max_length=255, null=True, blank=True, verbose_name="最后一次登录Token", + help_text="最后一次登录Token") def set_password(self, raw_password): super().set_password(hashlib.md5(raw_password.encode(encoding="UTF-8")).hexdigest()) @@ -87,9 +93,11 @@ class Role(CoreModel): (3, "全部数据权限"), (4, "自定数据权限"), ) - data_range = models.IntegerField(default=0, choices=DATASCOPE_CHOICES, verbose_name="数据权限范围", help_text="数据权限范围") + data_range = models.IntegerField(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="数据权限-关联部门") + dept = models.ManyToManyField(to="Dept", verbose_name="数据权限-关联部门", db_constraint=False, + help_text="数据权限-关联部门") menu = models.ManyToManyField(to="Menu", verbose_name="关联菜单", db_constraint=False, help_text="关联菜单") permission = models.ManyToManyField( to="MenuButton", verbose_name="关联菜单的接口按钮", db_constraint=False, help_text="关联菜单的接口按钮" @@ -104,7 +112,8 @@ class Role(CoreModel): class Dept(CoreModel): name = models.CharField(max_length=64, verbose_name="部门名称", help_text="部门名称") - key = models.CharField(max_length=64, unique=True,null=True,blank=True, verbose_name="关联字符", help_text="关联字符") + key = models.CharField(max_length=64, unique=True, null=True, blank=True, 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="联系电话") @@ -168,10 +177,12 @@ class Menu(CoreModel): is_catalog = models.BooleanField(default=False, 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="组件名称") + component_name = models.CharField(max_length=50, verbose_name="组件名称", null=True, blank=True, + help_text="组件名称") status = models.BooleanField(default=True, blank=True, verbose_name="菜单状态", help_text="菜单状态") cache = models.BooleanField(default=False, blank=True, verbose_name="是否页面缓存", help_text="是否页面缓存") - visible = models.BooleanField(default=True, blank=True, verbose_name="侧边栏中是否显示", help_text="侧边栏中是否显示") + visible = models.BooleanField(default=True, blank=True, verbose_name="侧边栏中是否显示", + help_text="侧边栏中是否显示") class Meta: db_table = table_prefix + "system_menu" @@ -198,7 +209,8 @@ class MenuButton(CoreModel): (2, "PUT"), (3, "DELETE"), ) - method = models.IntegerField(default=0, verbose_name="接口请求方法", null=True, blank=True, help_text="接口请求方法") + method = models.IntegerField(default=0, verbose_name="接口请求方法", null=True, blank=True, + help_text="接口请求方法") class Meta: db_table = table_prefix + "system_menu_button" @@ -219,7 +231,8 @@ class Dictionary(CoreModel): (7, "images"), ) 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="字典编号/实际值") + value = models.CharField(max_length=200, blank=True, null=True, verbose_name="字典编号", + help_text="字典编号/实际值") parent = models.ForeignKey( to="self", related_name="sublist", @@ -232,7 +245,8 @@ class Dictionary(CoreModel): ) type = models.IntegerField(choices=TYPE_LIST, default=0, verbose_name="数据值类型", help_text="数据值类型") color = models.CharField(max_length=20, blank=True, null=True, verbose_name="颜色", help_text="颜色") - is_value = models.BooleanField(default=False, verbose_name="是否为value值", help_text="是否为value值,用来做具体值存放") + is_value = models.BooleanField(default=False, verbose_name="是否为value值", + help_text="是否为value值,用来做具体值存放") status = models.BooleanField(default=True, verbose_name="状态", help_text="状态") sort = models.IntegerField(default=1, verbose_name="显示排序", null=True, blank=True, help_text="显示排序") remark = models.CharField(max_length=2000, blank=True, null=True, verbose_name="备注", help_text="备注") @@ -254,14 +268,20 @@ class Dictionary(CoreModel): class OperationLog(CoreModel): - request_modular = models.CharField(max_length=64, verbose_name="请求模块", null=True, blank=True, help_text="请求模块") - request_path = models.CharField(max_length=400, verbose_name="请求地址", null=True, blank=True, help_text="请求地址") + request_modular = models.CharField(max_length=64, verbose_name="请求模块", null=True, blank=True, + help_text="请求模块") + request_path = models.CharField(max_length=400, 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_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_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="响应状态") @@ -302,7 +322,8 @@ class FileList(CoreModel): class Area(CoreModel): name = models.CharField(max_length=100, verbose_name="名称", help_text="名称") code = models.CharField(max_length=20, verbose_name="地区编码", help_text="地区编码", unique=True, db_index=True) - level = models.BigIntegerField(verbose_name="地区层级(1省份 2城市 3区县 4乡级)", help_text="地区层级(1省份 2城市 3区县 4乡级)") + level = models.BigIntegerField(verbose_name="地区层级(1省份 2城市 3区县 4乡级)", + help_text="地区层级(1省份 2城市 3区县 4乡级)") pinyin = models.CharField(max_length=255, verbose_name="拼音", help_text="拼音") initials = models.CharField(max_length=20, verbose_name="首字母", help_text="首字母") enable = models.BooleanField(default=True, verbose_name="是否启用", help_text="是否启用") @@ -335,8 +356,10 @@ class ApiWhiteList(CoreModel): (2, "PUT"), (3, "DELETE"), ) - method = models.IntegerField(default=0, verbose_name="接口请求方法", null=True, blank=True, help_text="接口请求方法") - enable_datasource = models.BooleanField(default=True, verbose_name="激活数据权限", help_text="激活数据权限", blank=True) + method = models.IntegerField(default=0, verbose_name="接口请求方法", null=True, blank=True, + help_text="接口请求方法") + enable_datasource = models.BooleanField(default=True, verbose_name="激活数据权限", help_text="激活数据权限", + blank=True) class Meta: db_table = table_prefix + "api_white_list" @@ -356,8 +379,8 @@ class SystemConfig(CoreModel): help_text="父级", ) title = models.CharField(max_length=50, verbose_name="标题", help_text="标题") - key = models.CharField(max_length=100, verbose_name="键", help_text="键", db_index=True) - value = models.JSONField(max_length=200, verbose_name="值", help_text="值", null=True, blank=True) + key = models.CharField(max_length=200, verbose_name="键", help_text="键", db_index=True) + value = models.JSONField(max_length=500, verbose_name="值", help_text="值", null=True, blank=True) sort = models.IntegerField(default=0, verbose_name="排序", help_text="排序", blank=True) status = models.BooleanField(default=True, verbose_name="启用状态", help_text="启用状态") data_options = models.JSONField(verbose_name="数据options", help_text="数据options", null=True, blank=True) @@ -383,7 +406,7 @@ class SystemConfig(CoreModel): choices=FORM_ITEM_TYPE_LIST, verbose_name="表单类型", help_text="表单类型", default=0, blank=True ) rule = models.JSONField(null=True, blank=True, verbose_name="校验规则", help_text="校验规则") - placeholder = models.CharField(max_length=50, null=True, blank=True, verbose_name="提示信息", help_text="提示信息") + placeholder = models.CharField(max_length=100, null=True, blank=True, verbose_name="提示信息", help_text="提示信息") setting = models.JSONField(null=True, blank=True, verbose_name="配置", help_text="配置") class Meta: @@ -415,8 +438,15 @@ class SystemConfig(CoreModel): class LoginLog(CoreModel): - LOGIN_TYPE_CHOICES = ((1, "普通登录"), (2, "微信扫码登录"), (3, "飞书扫码登录"), (4, "钉钉扫码登录")) - username = models.CharField(max_length=32, verbose_name="登录用户名", null=True, blank=True, help_text="登录用户名") + LOGIN_TYPE_CHOICES = ( + (1, "普通登录"), + (2, "普通扫码登录"), + (3, "微信扫码登录"), + (4, "飞书扫码登录"), + (5, "钉钉扫码登录"), + (6, "短信登录") + ) + username = models.CharField(max_length=150, 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.TextField(verbose_name="agent信息", null=True, blank=True, help_text="agent信息") browser = models.CharField(max_length=200, verbose_name="浏览器名", null=True, blank=True, help_text="浏览器名") @@ -428,11 +458,13 @@ class LoginLog(CoreModel): district = models.CharField(max_length=50, verbose_name="县区", null=True, blank=True, help_text="县区") isp = models.CharField(max_length=50, verbose_name="运营商", null=True, blank=True, help_text="运营商") area_code = models.CharField(max_length=50, verbose_name="区域代码", null=True, blank=True, help_text="区域代码") - country_english = models.CharField(max_length=50, verbose_name="英文全称", null=True, blank=True, help_text="英文全称") + country_english = models.CharField(max_length=50, verbose_name="英文全称", null=True, blank=True, + help_text="英文全称") country_code = models.CharField(max_length=50, verbose_name="简称", null=True, blank=True, help_text="简称") longitude = models.CharField(max_length=50, verbose_name="经度", null=True, blank=True, help_text="经度") latitude = models.CharField(max_length=50, verbose_name="纬度", null=True, blank=True, help_text="纬度") - login_type = models.IntegerField(default=1, choices=LOGIN_TYPE_CHOICES, verbose_name="登录类型", help_text="登录类型") + login_type = models.IntegerField(default=1, choices=LOGIN_TYPE_CHOICES, verbose_name="登录类型", + help_text="登录类型") class Meta: db_table = table_prefix + "system_login_log" @@ -442,14 +474,16 @@ class LoginLog(CoreModel): class MessageCenter(CoreModel): - title = models.CharField(max_length=100,verbose_name="标题",help_text="标题") - content = models.TextField(verbose_name="内容",help_text="内容") - target_type=models.IntegerField(default=0,verbose_name="目标类型",help_text="目标类型") - target_user = models.ManyToManyField(to=Users,related_name='user',through='MessageCenterTargetUser', through_fields=('messagecenter','users'),blank=True,verbose_name="目标用户",help_text="目标用户") - target_dept = models.ManyToManyField(to=Dept, blank=True, db_constraint=False, - verbose_name="目标部门", help_text="目标部门") - target_role = models.ManyToManyField(to=Role, blank=True, db_constraint=False, - verbose_name="目标角色", help_text="目标角色") + title = models.CharField(max_length=100, verbose_name="标题", help_text="标题") + content = models.TextField(verbose_name="内容", help_text="内容") + target_type = models.IntegerField(default=0, verbose_name="目标类型", help_text="目标类型") + target_user = models.ManyToManyField(to=Users, related_name='user', through='MessageCenterTargetUser', + through_fields=('messagecenter', 'users'), blank=True, verbose_name="目标用户", + help_text="目标用户") + target_dept = models.ManyToManyField(to=Dept, blank=True, db_constraint=False, + verbose_name="目标部门", help_text="目标部门") + target_role = models.ManyToManyField(to=Role, blank=True, db_constraint=False, + verbose_name="目标角色", help_text="目标角色") class Meta: db_table = table_prefix + "message_center" @@ -457,10 +491,13 @@ class MessageCenter(CoreModel): verbose_name_plural = verbose_name ordering = ("-create_datetime",) + class MessageCenterTargetUser(CoreModel): - users = models.ForeignKey(Users,related_name="target_user", on_delete=models.CASCADE,db_constraint=False,verbose_name="关联用户表",help_text="关联用户表") - messagecenter = models.ForeignKey(MessageCenter, on_delete=models.CASCADE,db_constraint=False,verbose_name="关联消息中心表",help_text="关联消息中心表") - is_read = models.BooleanField(default=False,blank=True,null=True,verbose_name="是否已读",help_text="是否已读") + users = models.ForeignKey(Users, related_name="target_user", on_delete=models.CASCADE, db_constraint=False, + verbose_name="关联用户表", help_text="关联用户表") + messagecenter = models.ForeignKey(MessageCenter, on_delete=models.CASCADE, db_constraint=False, + verbose_name="关联消息中心表", help_text="关联消息中心表") + is_read = models.BooleanField(default=False, blank=True, null=True, verbose_name="是否已读", help_text="是否已读") class Meta: db_table = table_prefix + "message_center_target_user" diff --git a/backend/dvadmin/system/views/login.py b/backend/dvadmin/system/views/login.py index 124f26b..a2258d3 100644 --- a/backend/dvadmin/system/views/login.py +++ b/backend/dvadmin/system/views/login.py @@ -70,6 +70,7 @@ class LoginSerializer(TokenObtainPairSerializer): default_error_messages = {"no_active_account": _("账号/密码错误")} def validate(self, attrs): + captcha = self.initial_data.get("captcha", None) if dispatch.get_system_config_values("base.captcha_state"): if captcha is None: diff --git a/backend/dvadmin/utils/models.py b/backend/dvadmin/utils/models.py index af7d71c..9f741b0 100644 --- a/backend/dvadmin/utils/models.py +++ b/backend/dvadmin/utils/models.py @@ -7,12 +7,15 @@ @Remark: 公共基础model类 """ import uuid +from datetime import date, timedelta from django.apps import apps -from django.db import models +from django.db import models, connection, ProgrammingError from django.db.models import QuerySet from application import settings +from application.dispatch import is_tenants_mode + table_prefix = settings.TABLE_PREFIX # 数据库表名前缀 @@ -40,10 +43,17 @@ class SoftDeleteManager(models.Manager): return SoftDeleteQuerySet(self.model, using=self._db).exclude(is_deleted=False) return SoftDeleteQuerySet(self.model).exclude(is_deleted=True) - def get_by_natural_key(self,name): + def get_by_natural_key(self, name): return SoftDeleteQuerySet(self.model).get(username=name) +def get_month_range(start_day, end_day): + months = (end_day.year - start_day.year) * 12 + end_day.month - start_day.month + month_range = ['%s-%s-01' % (start_day.year + mon // 12, str(mon % 12 + 1).zfill(2)) + for mon in range(start_day.month - 1, start_day.month + months)] + return month_range + + class SoftDeleteModel(models.Model): """ 软删除模型 @@ -73,10 +83,13 @@ class CoreModel(models.Model): id = models.BigAutoField(primary_key=True, help_text="Id", verbose_name="Id") description = models.CharField(max_length=255, verbose_name="描述", null=True, blank=True, help_text="描述") creator = models.ForeignKey(to=settings.AUTH_USER_MODEL, related_query_name='creator_query', null=True, - verbose_name='创建人', help_text="创建人", on_delete=models.SET_NULL, db_constraint=False) + verbose_name='创建人', help_text="创建人", on_delete=models.SET_NULL, + db_constraint=False) modifier = models.CharField(max_length=255, null=True, blank=True, help_text="修改人", verbose_name="修改人") - dept_belong_id = models.CharField(max_length=255, help_text="数据归属部门", null=True, blank=True, verbose_name="数据归属部门") - update_datetime = models.DateTimeField(auto_now=True, null=True, blank=True, help_text="修改时间", verbose_name="修改时间") + dept_belong_id = models.CharField(max_length=255, help_text="数据归属部门", null=True, blank=True, + verbose_name="数据归属部门") + update_datetime = models.DateTimeField(auto_now=True, null=True, blank=True, help_text="修改时间", + verbose_name="修改时间") create_datetime = models.DateTimeField(auto_now_add=True, null=True, blank=True, help_text="创建时间", verbose_name="创建时间") @@ -86,6 +99,113 @@ class CoreModel(models.Model): verbose_name_plural = verbose_name +class AddPostgresPartitionedBase: + """ + pgsql表分表基类 + """ + + @classmethod + def add_hash_partition(cls, number=36): + """ + 创建分区表 + :return: + """ + if cls.PartitioningMeta.method != 'hash': + raise ProgrammingError("表分区错误,无法进行分区") + schema_editor = connection.schema_editor() + if is_tenants_mode(): + schema_editor.sql_add_hash_partition = f'CREATE TABLE "{connection.tenant.schema_name}".%s PARTITION OF "{connection.tenant.schema_name}".%s FOR VALUES WITH (MODULUS %s, REMAINDER %s)' + for item in range(number): + try: + schema_editor.add_hash_partition( + model=cls, + name="_" + str(item), + modulus=number, + remainder=item, + ) + except ProgrammingError as e: + print(f"{cls.__name__}分表失败:" + str(e).rstrip('\n')) + return + + @classmethod + def add_range_day_partition(cls, day=7): + """ + 按照创建时间"天"分表 + :return: + """ + if cls.PartitioningMeta.method != 'range': + raise ProgrammingError("表分区错误,无法进行分区") + day_before = date.today().strftime("%Y-%m-%d") + schema_editor = connection.schema_editor() + if is_tenants_mode(): + schema_editor.sql_add_range_partition = ( + f'CREATE TABLE "{connection.tenant.schema_name}".%s PARTITION OF "{connection.tenant.schema_name}".%s FOR VALUES FROM (%s) TO (%s)' + ) + for index in range(day): + try: + day_following = (date.today() + timedelta(days=index + 1)).strftime("%Y-%m-%d") + schema_editor.add_range_partition( + model=cls, + name=f"{day_before}_{day_following}", + from_values=day_before, + to_values=day_following, + ) + day_before = day_following + except ProgrammingError as e: + print(f"{cls.__name__}分表失败:" + str(e).rstrip('\n')) + return + + @classmethod + def add_range_month_partition(cls, start_date, end_date): + """ + 按照创建时间"月"分表 + :return: + """ + if cls.PartitioningMeta.method != 'range': + raise ProgrammingError("表分区错误,无法进行分区") + range_month_partition_list = get_month_range(start_date, end_date) + schema_editor = connection.schema_editor() + if is_tenants_mode(): + schema_editor.sql_add_range_partition = ( + f'CREATE TABLE "{connection.tenant.schema_name}".%s PARTITION OF "{connection.tenant.schema_name}".%s FOR VALUES FROM (%s) TO (%s)' + ) + for index, ele in enumerate(range_month_partition_list): + if index == 0: + continue + try: + schema_editor.add_range_partition( + model=cls, + name=f"{range_month_partition_list[index - 1][:-3]}_{ele[:-3]}", + from_values=range_month_partition_list[index - 1], + to_values=ele, + ) + except ProgrammingError as e: + print(f"{cls.__name__}分表失败:" + str(e).rstrip('\n')) + return + + @classmethod + def add_list_partition(cls, unique_value): + """ + 按照某个值进行分区 + :param unique_value: + :return: + """ + if cls.PartitioningMeta.method != 'list': + raise ProgrammingError("表分区错误,无法进行分区") + schema_editor = connection.schema_editor() + if is_tenants_mode(): + schema_editor.sql_add_list_partition = ( + f'CREATE TABLE "{connection.tenant.schema_name}".%s PARTITION OF "{connection.tenant.schema_name}".%s FOR VALUES IN (%s)' + ) + try: + schema_editor.add_list_partition( + model=cls, + name=f"_{unique_value}", + values=[unique_value], + ) + except ProgrammingError as e: + print(f"{cls.__name__}分表失败:" + str(e).rstrip('\n')) + return def get_all_models_objects(model_name=None): @@ -111,4 +231,4 @@ def get_all_models_objects(model_name=None): settings.ALL_MODELS_OBJECTS.setdefault(item.__name__, {"table": table, "object": item}) if model_name: return settings.ALL_MODELS_OBJECTS[model_name] or {} - return settings.ALL_MODELS_OBJECTS or {} \ No newline at end of file + return settings.ALL_MODELS_OBJECTS or {} diff --git a/backend/dvadmin/utils/request_util.py b/backend/dvadmin/utils/request_util.py index a87ac27..441ab5d 100644 --- a/backend/dvadmin/utils/request_util.py +++ b/backend/dvadmin/utils/request_util.py @@ -202,7 +202,7 @@ def get_ip_analysis(ip): return data -def save_login_log(request): +def save_login_log(request, login_type=1): """ 保存登录日志 :return: @@ -214,6 +214,7 @@ def save_login_log(request): analysis_data['agent'] = str(parse(request.META['HTTP_USER_AGENT'])) analysis_data['browser'] = get_browser(request) analysis_data['os'] = get_os(request) + analysis_data['login_type'] = login_type analysis_data['creator_id'] = request.user.id analysis_data['dept_belong_id'] = getattr(request.user, 'dept_id', '') LoginLog.objects.create(**analysis_data) From 2be51eb992a9c5208881461ad259bd9d8bcc754c Mon Sep 17 00:00:00 2001 From: sanfengpeng Date: Fri, 14 Apr 2023 18:24:23 +0800 Subject: [PATCH 06/33] 1 --- web/src/views/dashboard/workbench/components/ aac.vue | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 web/src/views/dashboard/workbench/components/ aac.vue diff --git a/web/src/views/dashboard/workbench/components/ aac.vue b/web/src/views/dashboard/workbench/components/ aac.vue new file mode 100644 index 0000000..e69de29 From e1868b7a56a5ec4f176e6a2547b64f256b2b8bba Mon Sep 17 00:00:00 2001 From: layman_one <359573099@qq.com> Date: Fri, 14 Apr 2023 18:36:51 +0800 Subject: [PATCH 07/33] =?UTF-8?q?4-14=E9=A6=96=E9=A1=B5=E7=BB=9F=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/dvadmin/system/urls.py | 2 + backend/dvadmin/system/views/datav.py | 95 +++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 backend/dvadmin/system/views/datav.py diff --git a/backend/dvadmin/system/urls.py b/backend/dvadmin/system/urls.py index fab79f9..73f1d92 100644 --- a/backend/dvadmin/system/urls.py +++ b/backend/dvadmin/system/urls.py @@ -4,6 +4,7 @@ from rest_framework import routers from dvadmin.system.views.api_white_list import ApiWhiteListViewSet from dvadmin.system.views.area import AreaViewSet from dvadmin.system.views.clause import PrivacyView, TermsServiceView +from dvadmin.system.views.datav import DataVViewSet from dvadmin.system.views.dept import DeptViewSet from dvadmin.system.views.dictionary import DictionaryViewSet from dvadmin.system.views.file_list import FileViewSet @@ -40,5 +41,6 @@ urlpatterns = [ path('dept_lazy_tree/', DeptViewSet.as_view({'get': 'dept_lazy_tree'})), path('clause/privacy.html', PrivacyView.as_view()), path('clause/terms_service.html', TermsServiceView.as_view()), + path('homepage_statistics/', DataVViewSet.as_view({'get': 'homepage_statistics'})), ] urlpatterns += system_url.urls diff --git a/backend/dvadmin/system/views/datav.py b/backend/dvadmin/system/views/datav.py new file mode 100644 index 0000000..0da4a4e --- /dev/null +++ b/backend/dvadmin/system/views/datav.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# @Time : 2023/4/14 15:49 +# @Author : harry +import datetime +import json +import time + +from django.db.models import Count +from rest_framework.decorators import action +from rest_framework.permissions import IsAuthenticated +from rest_framework.viewsets import GenericViewSet + +from dvadmin.system.models import Users, LoginLog, FileList +from dvadmin.system.views.login_log import LoginLogSerializer +from dvadmin.utils.json_response import DetailResponse + + +def jx_timestamp(): + cur_time = datetime.datetime.now() + a = datetime.datetime.strftime(cur_time, '%Y-%m-%d %H:%M:%S') + timeStamp = int(time.mktime(time.strptime(a, "%Y-%m-%d %H:%M:%S"))) + timeArray = time.localtime(timeStamp) + otherStyleTime = time.strftime("%Y-%m-%d %H:%M:%S", timeArray) + return otherStyleTime + + +class DataVViewSet(GenericViewSet): + queryset = LoginLog.objects.all() + serializer_class = LoginLogSerializer + extra_filter_backends = [] + ordering_fields = ['create_datetime'] + + @action(methods=["GET"], detail=False, permission_classes=[IsAuthenticated]) + def homepage_statistics(self, request): + # Users 新增 + # LoginLog # 最后登录 + timestr = jx_timestamp().split(" ") + min_time = datetime.datetime.strptime(timestr[0] + " " + "00:00:00", "%Y-%m-%d %H:%M:%S") + max_time = datetime.datetime.strptime(timestr[0] + " " + "23:59:59", "%Y-%m-%d %H:%M:%S") + # 今日注册 + today_register = Users.objects.filter(create_datetime__gte=min_time, is_superuser=0).count() + # 今日登录 + today_login = len(set(LoginLog.objects.filter(create_datetime__gte=min_time).values_list('username'))) + # 三日新增 + Three_days_register = Users.objects.filter( + create_datetime__gte=min_time - datetime.timedelta(days=3), is_superuser=0).count() + # 七日新增 + Seven_days_register = Users.objects.filter( + create_datetime__gte=min_time - datetime.timedelta(days=7), is_superuser=0).count() + # 七日活跃 + Seven_days_login = len(set(LoginLog.objects.filter( + create_datetime__gte=min_time - datetime.timedelta(days=7)).values_list('username'))) + # 月活跃 + month_login = len(set(LoginLog.objects.filter( + create_datetime__gte=min_time - datetime.timedelta(days=30)).values_list('username'))) + # 七日用户登录数 + sum_days_login_list = [] + for i in range(7): + sum_days_login_list.append({"time": (min_time + datetime.timedelta(days=-i)).strftime("%Y-%m-%d"), + "count": len(set(LoginLog.objects.filter( + create_datetime__lte=max_time - datetime.timedelta(days=i), + create_datetime__gte=min_time - datetime.timedelta(days=i)).values_list( + 'username')))}) + + # 七日注册用户数 + sum_days_register_list = [] + for i in range(7): + sum_days_register_list.append( + {"time": (min_time + datetime.timedelta(days=-i)).strftime("%Y-%m-%d"), "count": Users.objects.filter( + create_datetime__lte=max_time - datetime.timedelta(days=i), + create_datetime__gte=min_time - datetime.timedelta(days=i), is_superuser=0).count()}) + # 用户总数 + sum_register = Users.objects.filter(is_superuser=0).count() + # FileList 附件 + today_f_l = FileList.objects.filter(create_datetime__gte=min_time).count() + sum_f_l = FileList.objects.all().count() + # 今日附件 + today_file = {'count': today_f_l, "occupy_space": 0} + # 总附件 + sum_file = {'count': sum_f_l, "occupy_space": 0} + data = { + "today_register": today_register, + "today_login": today_login, + "Three_days_register": Three_days_register, + "Seven_days_register": Seven_days_register, + "Seven_days_login": Seven_days_login, + "month_login": month_login, + "sum_days_login_list": sum_days_login_list, + "sum_days_register_list": sum_days_register_list, + "sum_register": sum_register, + "today_file": today_file, + "sum_file": sum_file, + } + return DetailResponse(data=data, msg="获取成功") From fb53e8b6cb46272e7ffca353aeb0c327483dc5e6 Mon Sep 17 00:00:00 2001 From: sanfengpeng Date: Fri, 14 Apr 2023 18:43:38 +0800 Subject: [PATCH 08/33] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=8E=A7=E5=88=B6?= =?UTF-8?q?=E5=8F=B0=E9=83=A8=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 0 -> 6148 bytes package-lock.json | 6 + web/.env.development | 2 +- web/package.json | 2 +- web/src/main.js | 4 +- .../dashboard/workbench/components/ aac.vue | 0 .../workbench/components/attachment.vue | 109 ++++++++++++ .../workbench/components/database.vue | 108 ++++++++++++ .../dashboard/workbench/components/member.vue | 85 +++++++++ .../workbench/components/newUsers.vue | 162 ++++++++++++++++++ .../workbench/components/registeredUser.vue | 92 ++++++++++ .../workbench/components/sumTotal.vue | 109 ++++++++++++ .../workbench/components/userIogin.vue | 98 +++++++++++ 13 files changed, 774 insertions(+), 3 deletions(-) create mode 100644 .DS_Store create mode 100644 package-lock.json delete mode 100644 web/src/views/dashboard/workbench/components/ aac.vue create mode 100644 web/src/views/dashboard/workbench/components/attachment.vue create mode 100644 web/src/views/dashboard/workbench/components/database.vue create mode 100644 web/src/views/dashboard/workbench/components/member.vue create mode 100644 web/src/views/dashboard/workbench/components/newUsers.vue create mode 100644 web/src/views/dashboard/workbench/components/registeredUser.vue create mode 100644 web/src/views/dashboard/workbench/components/sumTotal.vue create mode 100644 web/src/views/dashboard/workbench/components/userIogin.vue diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..a7f0f6b0c032283e13bd77ecd8ad2b5acf6f9d11 GIT binary patch literal 6148 zcmeHKO>5gg5S_K%SWa3nrG;Dyf?gfhsf(fXqB!;;&<}`0duWTRjZ7<|XpLn@6l2i2 z{VRoD`%C&?dTM88R}jhRwFzYhX5W6yo7Fy{T`d5J;WFF@Xaj(QPT1JS;tHd2@(rt* z9^whkF@*%eqgb8Fcq7_&SOu&CH%$ThcAFp}fKxbwOW&`OI6~XP0ebg08`c2sLI}!4 z&tVU13eI7MWs3YRe8yI+_kbdYcu>i)UCJ@xc`wQw_+H^O;W-?^A&lWA_%JR#Z{P{tXM_uV};kM@HQB%-M35H)gi;|viv-} z(kr55md<3%v;UB@I7%12-cM1hH*Re;ou;$ny!St;%wGhHWjYMzZ>e>nR4j{nAYVt* zY|_4WsFFnxCDS<*qHu~K@7_d7sIsA2CSl54Uk^Afr!{Hsu2y^d{f^ro4AvcY_4IMC z<38yR*6WsY|KX!&$CI=8JW*dz5j26jKieIH1<+eDYrgR3Nvsmmu!t_AEMAWS<~=w& z*E7AH)hb{WxWNk0{@|h$dIociymer~R{+EYcC%rfej1458uSe28gT?oXey$n3UkE} znvVUhiSrER8Z{k+xqJvSvoJRl!Lwt2m%~AL8f|G6unLqFsOx5%&j0b>@Bd|zZCM4Z z0{@i)qA~JELtK(MTQ?R*XRV9=0iBHEa*a&E!W_q3p`&;goejrasvvp>bB)-8W`6`& M23uGK{;2|g0Cat_f&c&j literal 0 HcmV?d00001 diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..ebaca02 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "django-vue-admin", + "lockfileVersion": 2, + "requires": true, + "packages": {} +} diff --git a/web/.env.development b/web/.env.development index 2b35a9a..65fcb3a 100644 --- a/web/.env.development +++ b/web/.env.development @@ -5,5 +5,5 @@ VUE_APP_TITLE=企业级后台管理系统 # 启用权限管理 VUE_APP_PM_ENABLED = true # 后端接口地址及端口(域名) -VUE_APP_API = "http://127.0.0.1:8000" +VUE_APP_API = "https://demo.django-vue-admin.com/api" diff --git a/web/package.json b/web/package.json index 086e51b..f487fce 100644 --- a/web/package.json +++ b/web/package.json @@ -23,7 +23,7 @@ "d2-crud-x": "^2.17.9", "d2p-extends": "^2.17.9", "dayjs": "^1.8.17", - "echarts": "^5.1.2", + "echarts": "^5.4.2", "el-phone-number-input": "^1.1.5", "element-ui": "^2.15.5", "faker": "^4.1.0", diff --git a/web/src/main.js b/web/src/main.js index c5a81e0..3adfccd 100644 --- a/web/src/main.js +++ b/web/src/main.js @@ -36,13 +36,15 @@ import md5 from 'js-md5' import websocket from '@/api/websocket' import util from '@/libs/util' +//引入echarts +import * as echarts from "echarts" // 核心插件 Vue.use(d2Admin) Vue.use(VXETable) Vue.prototype.$md5 = md5 Vue.prototype.$util = util Vue.prototype.$websocket = websocket - +Vue.prototype.$echarts = echarts //注册echarts组件 new Vue({ router, store, diff --git a/web/src/views/dashboard/workbench/components/ aac.vue b/web/src/views/dashboard/workbench/components/ aac.vue deleted file mode 100644 index e69de29..0000000 diff --git a/web/src/views/dashboard/workbench/components/attachment.vue b/web/src/views/dashboard/workbench/components/attachment.vue new file mode 100644 index 0000000..fcf3584 --- /dev/null +++ b/web/src/views/dashboard/workbench/components/attachment.vue @@ -0,0 +1,109 @@ + + + + + + \ No newline at end of file diff --git a/web/src/views/dashboard/workbench/components/database.vue b/web/src/views/dashboard/workbench/components/database.vue new file mode 100644 index 0000000..e545bab --- /dev/null +++ b/web/src/views/dashboard/workbench/components/database.vue @@ -0,0 +1,108 @@ + + + + + + \ No newline at end of file diff --git a/web/src/views/dashboard/workbench/components/member.vue b/web/src/views/dashboard/workbench/components/member.vue new file mode 100644 index 0000000..c27b658 --- /dev/null +++ b/web/src/views/dashboard/workbench/components/member.vue @@ -0,0 +1,85 @@ + + + + + + \ No newline at end of file diff --git a/web/src/views/dashboard/workbench/components/newUsers.vue b/web/src/views/dashboard/workbench/components/newUsers.vue new file mode 100644 index 0000000..62b00ed --- /dev/null +++ b/web/src/views/dashboard/workbench/components/newUsers.vue @@ -0,0 +1,162 @@ + + + + + + \ No newline at end of file diff --git a/web/src/views/dashboard/workbench/components/registeredUser.vue b/web/src/views/dashboard/workbench/components/registeredUser.vue new file mode 100644 index 0000000..3f1da6e --- /dev/null +++ b/web/src/views/dashboard/workbench/components/registeredUser.vue @@ -0,0 +1,92 @@ + + + + + + \ No newline at end of file diff --git a/web/src/views/dashboard/workbench/components/sumTotal.vue b/web/src/views/dashboard/workbench/components/sumTotal.vue new file mode 100644 index 0000000..8bdb321 --- /dev/null +++ b/web/src/views/dashboard/workbench/components/sumTotal.vue @@ -0,0 +1,109 @@ + + + + + + \ No newline at end of file diff --git a/web/src/views/dashboard/workbench/components/userIogin.vue b/web/src/views/dashboard/workbench/components/userIogin.vue new file mode 100644 index 0000000..b00fe46 --- /dev/null +++ b/web/src/views/dashboard/workbench/components/userIogin.vue @@ -0,0 +1,98 @@ + + + + + + \ No newline at end of file From 77a31b0ec3556eafb8f2451fa2d1d4eb2465e961 Mon Sep 17 00:00:00 2001 From: sanfengpeng Date: Sat, 15 Apr 2023 16:37:52 +0800 Subject: [PATCH 09/33] 1 --- .DS_Store | Bin 6148 -> 8196 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/.DS_Store b/.DS_Store index a7f0f6b0c032283e13bd77ecd8ad2b5acf6f9d11..11a187cf4d21d48c8a93ec34c1704fed5ae709a4 100644 GIT binary patch delta 615 zcmZoMXmOBWU|?W$DortDU;r^WfEYvza8E20o2aKKCf{4TF>Oa|<>La)_~P zR^XV(yqKMXV`2kKJxB=)gC0XVLncEBOc_v&fwA++9b~!Od>5Cboctu97zcYRZ{5}} zM;uY*Q}D_cWI&t%)Wg8o`vF9;GbBwGV$rS#(hP|V$qd;HsSJ4xDJZUJ+x!Tk5?KYZ zTcS+16m5XG1!Gj zp%MtokR|w${msBIVe>|o!;JOFW-GFA`2)Sk%uo*WeiE_;xBq`h+X(R*Toz#qrYy2m zTICZ!K@8Pb7F?8n`9(Y@`}1&c09Ale L62shCKp?;kBwRtJZcO~n YJegm{6J!Si6U07{6Bstf^UPre0I53~U;qFB From b67d92def8038d57524284b1562847472311ffdb Mon Sep 17 00:00:00 2001 From: sanfengpeng Date: Sun, 16 Apr 2023 00:54:32 +0800 Subject: [PATCH 10/33] 1 --- web/src/views/dashboard/workbench/components/newUsers.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/views/dashboard/workbench/components/newUsers.vue b/web/src/views/dashboard/workbench/components/newUsers.vue index 62b00ed..99192de 100644 --- a/web/src/views/dashboard/workbench/components/newUsers.vue +++ b/web/src/views/dashboard/workbench/components/newUsers.vue @@ -116,7 +116,7 @@ methods: { initGet () { request({ - url: '' + url: '/api/system/homepage_statistics/' }).then(res => { const { data } = res // this.total = data.total From 4fe8605c2d2ae268e1518679e3ecb6379062b048 Mon Sep 17 00:00:00 2001 From: sanfengpeng Date: Sun, 16 Apr 2023 15:09:16 +0800 Subject: [PATCH 11/33] =?UTF-8?q?=E6=8E=A7=E5=88=B6=E5=8F=B0=E9=83=A8?= =?UTF-8?q?=E4=BB=B6=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../workbench/components/attachment.vue | 24 +-- .../workbench/components/database.vue | 23 +-- .../dashboard/workbench/components/member.vue | 17 +- .../workbench/components/newUsers.vue | 34 ++-- .../workbench/components/registeredUser.vue | 171 ++++++++-------- .../workbench/components/sumTotal.vue | 26 +-- .../workbench/components/userIogin.vue | 186 +++++++++--------- 7 files changed, 256 insertions(+), 225 deletions(-) diff --git a/web/src/views/dashboard/workbench/components/attachment.vue b/web/src/views/dashboard/workbench/components/attachment.vue index fcf3584..aabc132 100644 --- a/web/src/views/dashboard/workbench/components/attachment.vue +++ b/web/src/views/dashboard/workbench/components/attachment.vue @@ -9,7 +9,7 @@
-
{{ total || 0 }}
+
{{ count}}
附件数量
@@ -17,7 +17,7 @@ 实时
-
{{ total || 0 }}MB
+
{{ occupy_space }}MB
附件大小
@@ -42,18 +42,20 @@ isResizable: true, data() { return { - total: 0, + count:"", + occupy_space:"", }; }, methods: { - initGet() { - request({ - url: "", - }).then((res) => { - const { data } = res; - // this.total = data.total; - }); - }, + initGet () { + request({ + url: '/api/system/homepage_statistics/' + }).then((res)=>{ + this.count=res.data.sum_file.count; + this.occupy_space=res.data.sum_file.occupy_space; +; + }) + }, // 生成一个随机整数 randomColor() { const color = ["#50A8F4FF", "#FD6165FF", "#E679D8FF", "#F9AB5BFF"]; diff --git a/web/src/views/dashboard/workbench/components/database.vue b/web/src/views/dashboard/workbench/components/database.vue index e545bab..37842ef 100644 --- a/web/src/views/dashboard/workbench/components/database.vue +++ b/web/src/views/dashboard/workbench/components/database.vue @@ -9,7 +9,7 @@
-
{{ total || 0 }}
+
{{count }}
数据库数量
@@ -17,7 +17,7 @@ 实时
-
{{ total || 0 }}MB
+
{{ occupy_space}}MB
占用空间
@@ -41,18 +41,19 @@ isResizable: true, data() { return { - total: 0, + count:"", + occupy_space:"", }; }, methods: { - initGet() { - request({ - url: "", - }).then((res) => { - const { data } = res; - // this.total = data.total; - }); - }, + initGet () { + request({ + url: '/api/system/homepage_statistics/' + }).then((res)=>{ + this.count=res.data.sum_file.count; + this.occupy_space=res.data.sum_file.occupy_space; + }) + }, // 生成一个随机整数 randomColor() { const color = ["#50A8F4FF", "#FD6165FF", "#E679D8FF", "#F9AB5BFF"]; diff --git a/web/src/views/dashboard/workbench/components/member.vue b/web/src/views/dashboard/workbench/components/member.vue index c27b658..bf55d0b 100644 --- a/web/src/views/dashboard/workbench/components/member.vue +++ b/web/src/views/dashboard/workbench/components/member.vue @@ -5,7 +5,7 @@
-
{{total || 0}}
+
{{sum_register}}
@@ -31,18 +31,17 @@ isResizable: true, data () { return { - total: 0 + sum_register:"", } }, methods: { initGet () { - request({ - url: '' - }).then(res => { - const { data } = res - // this.total = data.total - }) - }, + request({ + url: '/api/system/homepage_statistics/' + }).then((res)=>{ + this.sum_register=res.data.sum_register + }) + }, // 生成一个随机整数 randomColor () { const color = [ diff --git a/web/src/views/dashboard/workbench/components/newUsers.vue b/web/src/views/dashboard/workbench/components/newUsers.vue index 99192de..cbe4518 100644 --- a/web/src/views/dashboard/workbench/components/newUsers.vue +++ b/web/src/views/dashboard/workbench/components/newUsers.vue @@ -9,7 +9,7 @@
-

{{total || 0}}

+

{{ newName }}

今日注册
@@ -24,7 +24,7 @@
-

{{total || 1}}

+

{{today_login}}

今日登录
@@ -39,7 +39,7 @@
-

{{total || 7}}

+

{{Three_days_register}}

三日新增
@@ -54,7 +54,7 @@
-

{{total || 15}}

+

{{Seven_days_register}}

七日新增
@@ -69,7 +69,7 @@
-

{{total || 24}}

+

{{Seven_days_login}}

七日活跃
@@ -84,7 +84,7 @@
-

{{total || 89}}

+

{{month_login}}

月活跃
@@ -96,6 +96,8 @@ + }, + mounted() { + this.myChart = this.$echarts.init(document.getElementById("main")); + this.initGet(); + this.drawLine(); + }, +}; + +.card-view { + border-radius: 10px; + color: #ffffff; +} +.el-card { + height: 100%; +} + \ No newline at end of file diff --git a/web/src/views/dashboard/workbench/components/sumTotal.vue b/web/src/views/dashboard/workbench/components/sumTotal.vue index 8bdb321..640c0e5 100644 --- a/web/src/views/dashboard/workbench/components/sumTotal.vue +++ b/web/src/views/dashboard/workbench/components/sumTotal.vue @@ -9,7 +9,7 @@
-
{{ total || 0 }}
+
{{ count }}
附件总数量
@@ -17,7 +17,7 @@ 实时
-
{{ total || 0 }}MB
+
{{ occupy_space}}MB
占用空间
@@ -42,18 +42,20 @@ isResizable: true, data() { return { - total: 0, + count:"", + occupy_space:"", }; }, methods: { - initGet() { - request({ - url: "", - }).then((res) => { - const { data } = res; - // this.total = data.total; - }); - }, + initGet () { + request({ + url: '/api/system/homepage_statistics/' + }).then((res)=>{ + this.count=res.data.today_file.count; + this.occupy_space=res.data.today_file.occupy_space; +; + }) + }, // 生成一个随机整数 randomColor() { const color = ["#50A8F4FF", "#FD6165FF", "#E679D8FF", "#F9AB5BFF"]; @@ -95,7 +97,7 @@ } .el-icon-s-flag { font-size: 12px; - margin-right: 132px; + margin-right: 130px; } } .real-time { diff --git a/web/src/views/dashboard/workbench/components/userIogin.vue b/web/src/views/dashboard/workbench/components/userIogin.vue index b00fe46..0d871cf 100644 --- a/web/src/views/dashboard/workbench/components/userIogin.vue +++ b/web/src/views/dashboard/workbench/components/userIogin.vue @@ -1,98 +1,106 @@ - - - - - \ No newline at end of file + + \ No newline at end of file From 4ce9e237a68fe0425f52ab74c93c1262024aa94d Mon Sep 17 00:00:00 2001 From: ahhui Date: Sun, 16 Apr 2023 17:34:00 +0800 Subject: [PATCH 12/33] =?UTF-8?q?=E6=9B=B4=E6=96=B0requirements?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/requirements.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/requirements.txt b/backend/requirements.txt index 17727f8..d07e365 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -8,8 +8,10 @@ django-comment-migrate==0.1.7 django-cors-headers==3.10.1 django-filter==22.1 django-ranged-response==0.2.0 +django-redis==5.2.0 django-restql==0.15.3 django-simple-captcha==0.5.17 +django-tenants==3.4.8 django-timezone-field==4.2.3 djangorestframework==3.14.0 djangorestframework-simplejwt==5.2.2 From 2ad933456305ffa0c7a7e94408401d10681642e8 Mon Sep 17 00:00:00 2001 From: ahhui Date: Sun, 16 Apr 2023 23:24:42 +0800 Subject: [PATCH 13/33] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=B8=8A=E4=B8=80?= =?UTF-8?q?=E4=B8=AA=E7=94=A8=E6=88=B7=E7=99=BB=E5=BD=95=E5=90=8E=E5=88=87?= =?UTF-8?q?=E6=8D=A2=E5=88=B0=E4=B8=8B=E4=B8=80=E4=B8=AA=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E7=99=BB=E5=BD=95=E6=98=AF=E8=B7=B3=E8=BD=AC=E5=88=B0404?= =?UTF-8?q?=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/views/system/login/base.vue | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web/src/views/system/login/base.vue b/web/src/views/system/login/base.vue index b6d7f42..792a5b1 100644 --- a/web/src/views/system/login/base.vue +++ b/web/src/views/system/login/base.vue @@ -107,7 +107,8 @@ export default { }) .then(() => { // 重定向对象不存在则返回顶层路径 - this.$router.replace(this.$route.query.redirect || '/') + // this.$router.replace(this.$route.query.redirect || '/') + this.$router.replace('/') }) .catch(() => { this.getCaptcha() From d40dc172db9e9ebfac300a78b732524d3dcef521 Mon Sep 17 00:00:00 2001 From: sanfengpeng Date: Mon, 17 Apr 2023 12:02:10 +0800 Subject: [PATCH 14/33] =?UTF-8?q?=E6=8E=A7=E5=88=B6=E5=8F=B0=E9=83=A8?= =?UTF-8?q?=E4=BB=B6=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 8196 -> 8196 bytes web/.env.development | 2 +- .../workbench/components/database.vue | 11 ++++++----- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.DS_Store b/.DS_Store index 11a187cf4d21d48c8a93ec34c1704fed5ae709a4..676bf9acd80f1159e2d31e9f057efdc7796a69d9 100644 GIT binary patch delta 241 zcmZp1XmOa}&nUeyU^hRb^kg0Z$+#}zDGUq@EDU-K=?s|+CAs-7E=f80NkB1<^^r^( z?O%^LqROY>l`qIJ3{K9^Edc6aVC=gvd82^v=4k?&Oy+_N1q_J{$qd;*GMyonL6;$i zAs@`wW5{AC2D0-!bMlj+b_)P?%L0v9vw4e<5+jGHk%5kav4!d6d%_`1(yu0)h=fRN l09nDzP!2RJsVulCFDE}Q9c1a|*D{jK6AO4YvrGJC2LOY}JU9RV delta 182 zcmZp1XmOa}&nUGqU^hRb)MOq3$+*rZcNiELSQzve(it)tN^)lnKm;Di!*ZQ8XD^;7@L_*RuBnc q;_{zdCK4hs0i=|fp`0O=A*n35C@&{JFCC 实时
-
{{ occupy_space}}MB
+
{{ space}}MB
占用空间
@@ -42,7 +42,7 @@ data() { return { count:"", - occupy_space:"", + space:"", }; }, methods: { @@ -50,8 +50,9 @@ request({ url: '/api/system/homepage_statistics/' }).then((res)=>{ - this.count=res.data.sum_file.count; - this.occupy_space=res.data.sum_file.occupy_space; + this.count=res.data.database_info.count; + this.space=res.data.database_info.space; +; }) }, // 生成一个随机整数 @@ -95,7 +96,7 @@ } .el-icon-s-flag { font-size: 12px; - margin-right: 132px; + margin-right: 130px; } } .real-time { From 6c63e19dcf35d352cd8e67f13854fbfdedcd63eb Mon Sep 17 00:00:00 2001 From: layman_one <359573099@qq.com> Date: Mon, 17 Apr 2023 12:04:57 +0800 Subject: [PATCH 15/33] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=BA=93=E7=BB=9F=E8=AE=A1=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/dvadmin/system/views/datav.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/backend/dvadmin/system/views/datav.py b/backend/dvadmin/system/views/datav.py index 0da4a4e..248b284 100644 --- a/backend/dvadmin/system/views/datav.py +++ b/backend/dvadmin/system/views/datav.py @@ -4,6 +4,7 @@ # @Author : harry import datetime import json +import re import time from django.db.models import Count @@ -11,9 +12,11 @@ from rest_framework.decorators import action from rest_framework.permissions import IsAuthenticated from rest_framework.viewsets import GenericViewSet +from conf.env import DATABASE_USER, DATABASE_NAME from dvadmin.system.models import Users, LoginLog, FileList from dvadmin.system.views.login_log import LoginLogSerializer from dvadmin.utils.json_response import DetailResponse +from django.db import connection def jx_timestamp(): @@ -79,6 +82,29 @@ class DataVViewSet(GenericViewSet): today_file = {'count': today_f_l, "occupy_space": 0} # 总附件 sum_file = {'count': sum_f_l, "occupy_space": 0} + + # 获取游标对象 + + cursor = connection.cursor() + + # 拿到游标对象后执行sql语句 + + cursor.execute("show tables;") + + # 获取所有的数据 + + rows = cursor.fetchall() + tables_list = [] + for row in rows: + tables_list.append(row) + cursor.execute( + "select table_schema as db, table_name as tb, table_rows as data_rows, index_length / 1024 as 'storage(KB)' from information_schema.tables where table_schema='{}';".format( + DATABASE_NAME)) + rows = cursor.fetchall() + sum_space = 0 + for row in rows: + sum_space += row[3] + database_info = {"count": len(tables_list), "space": round(sum_space / 1024, 2)} data = { "today_register": today_register, "today_login": today_login, @@ -91,5 +117,6 @@ class DataVViewSet(GenericViewSet): "sum_register": sum_register, "today_file": today_file, "sum_file": sum_file, + "database_info": database_info, } return DetailResponse(data=data, msg="获取成功") From cc66b945300bd32d45059288a0301d935eb8061e Mon Sep 17 00:00:00 2001 From: layman_one <359573099@qq.com> Date: Tue, 18 Apr 2023 11:21:22 +0800 Subject: [PATCH 16/33] =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E7=BB=9F?= =?UTF-8?q?=E8=AE=A1=E6=9F=A5=E8=AF=A2-=E4=BC=98=E5=8C=96=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E8=AF=AD=E5=8F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/dvadmin/system/views/datav.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/backend/dvadmin/system/views/datav.py b/backend/dvadmin/system/views/datav.py index 248b284..e6eb66e 100644 --- a/backend/dvadmin/system/views/datav.py +++ b/backend/dvadmin/system/views/datav.py @@ -29,6 +29,7 @@ def jx_timestamp(): class DataVViewSet(GenericViewSet): + permission_classes = [] queryset = LoginLog.objects.all() serializer_class = LoginLogSerializer extra_filter_backends = [] @@ -97,14 +98,19 @@ class DataVViewSet(GenericViewSet): tables_list = [] for row in rows: tables_list.append(row) + # cursor.execute( + # "select table_schema as db, table_name as tb, table_rows as data_rows, index_length / 1024 as 'storage(KB)' from information_schema.tables where table_schema='{}';".format( + # DATABASE_NAME)) cursor.execute( - "select table_schema as db, table_name as tb, table_rows as data_rows, index_length / 1024 as 'storage(KB)' from information_schema.tables where table_schema='{}';".format( + "select table_schema as table_db, sum(index_length) as storage,count(table_name ) as tables from information_schema.tables group by table_schema having table_db='{}';".format( DATABASE_NAME)) rows = cursor.fetchall() - sum_space = 0 + count = 0 + space = 0 for row in rows: - sum_space += row[3] - database_info = {"count": len(tables_list), "space": round(sum_space / 1024, 2)} + count = row[2] + space = round(row[1] / 1024 / 1024, 2) + database_info = {"count": count, "space": space} data = { "today_register": today_register, "today_login": today_login, From 08aba985b806dd691f086ae850f45eae1068e92f Mon Sep 17 00:00:00 2001 From: layman_one <359573099@qq.com> Date: Tue, 18 Apr 2023 11:22:53 +0800 Subject: [PATCH 17/33] =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E7=BB=9F?= =?UTF-8?q?=E8=AE=A1=E6=9F=A5=E8=AF=A2-=E6=B7=BB=E5=8A=A0=E6=9D=83?= =?UTF-8?q?=E9=99=90=E6=8E=A7=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/dvadmin/system/views/datav.py | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/dvadmin/system/views/datav.py b/backend/dvadmin/system/views/datav.py index e6eb66e..f406096 100644 --- a/backend/dvadmin/system/views/datav.py +++ b/backend/dvadmin/system/views/datav.py @@ -29,7 +29,6 @@ def jx_timestamp(): class DataVViewSet(GenericViewSet): - permission_classes = [] queryset = LoginLog.objects.all() serializer_class = LoginLogSerializer extra_filter_backends = [] From 5ff92536e429f0509974f90cb7f12da3f233fe3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BC=BA?= <1206709430@qq.com> Date: Fri, 21 Apr 2023 00:28:11 +0800 Subject: [PATCH 18/33] =?UTF-8?q?refactor:=20=F0=9F=8E=A8=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E9=A6=96=E9=A1=B5=E5=89=8D=E7=AB=AF=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/.env.development | 2 +- web/package.json | 4 +- web/src/main.js | 6 +- .../dashboard/workbench/components/about.vue | 22 +- .../workbench/components/attachment.vue | 111 ----- .../workbench/components/attachmentTotal.vue | 149 +++++++ .../workbench/components/dashboardImg.vue | 10 +- .../workbench/components/database.vue | 110 ----- .../workbench/components/databaseTotal.vue | 146 +++++++ .../workbench/components/loginTotal.vue | 103 +++++ .../dashboard/workbench/components/member.vue | 84 ---- .../workbench/components/newUsers.vue | 174 -------- .../workbench/components/registeredUser.vue | 240 ++++++++--- .../workbench/components/sumTotal.vue | 111 ----- .../dashboard/workbench/components/time.vue | 41 +- .../workbench/components/userIogin.vue | 106 ----- .../workbench/components/userLogin.vue | 205 +++++++++ .../workbench/components/usersActive.vue | 181 ++++++++ .../workbench/components/usersTotal.vue | 103 +++++ .../dashboard/workbench/components/ver.vue | 49 ++- .../workbench/components/welcome.vue | 38 +- web/src/views/dashboard/workbench/config.vue | 7 +- web/src/views/dashboard/workbench/index.vue | 123 ++++-- web/src/views/dashboard/workbench/init.js | 400 ++++++++++++------ 24 files changed, 1546 insertions(+), 979 deletions(-) delete mode 100644 web/src/views/dashboard/workbench/components/attachment.vue create mode 100644 web/src/views/dashboard/workbench/components/attachmentTotal.vue delete mode 100644 web/src/views/dashboard/workbench/components/database.vue create mode 100644 web/src/views/dashboard/workbench/components/databaseTotal.vue create mode 100644 web/src/views/dashboard/workbench/components/loginTotal.vue delete mode 100644 web/src/views/dashboard/workbench/components/member.vue delete mode 100644 web/src/views/dashboard/workbench/components/newUsers.vue delete mode 100644 web/src/views/dashboard/workbench/components/sumTotal.vue delete mode 100644 web/src/views/dashboard/workbench/components/userIogin.vue create mode 100644 web/src/views/dashboard/workbench/components/userLogin.vue create mode 100644 web/src/views/dashboard/workbench/components/usersActive.vue create mode 100644 web/src/views/dashboard/workbench/components/usersTotal.vue diff --git a/web/.env.development b/web/.env.development index 2540819..2b35a9a 100644 --- a/web/.env.development +++ b/web/.env.development @@ -5,5 +5,5 @@ VUE_APP_TITLE=企业级后台管理系统 # 启用权限管理 VUE_APP_PM_ENABLED = true # 后端接口地址及端口(域名) -VUE_APP_API = "http://192.168.1.22:8001/" +VUE_APP_API = "http://127.0.0.1:8000" diff --git a/web/package.json b/web/package.json index f487fce..b550393 100644 --- a/web/package.json +++ b/web/package.json @@ -1,6 +1,6 @@ { "name": "django-vue-admin", - "version": "2.1.2", + "version": "2.1.3", "scripts": { "serve": "vue-cli-service serve --open", "start": "npm run serve", @@ -40,7 +40,9 @@ "screenfull": "^5.0.2", "sortablejs": "^1.10.1", "ua-parser-js": "^0.7.20", + "viser-vue": "^2.4.8", "vue": "2.7.14", + "vue-echarts": "^6.5.4", "vue-grid-layout": "^2.4.0", "vue-i18n": "^8.15.1", "vue-infinite-scroll": "^2.0.2", diff --git a/web/src/main.js b/web/src/main.js index 3adfccd..fcdba4d 100644 --- a/web/src/main.js +++ b/web/src/main.js @@ -36,15 +36,15 @@ import md5 from 'js-md5' import websocket from '@/api/websocket' import util from '@/libs/util' -//引入echarts -import * as echarts from "echarts" +// 引入echarts +import * as echarts from 'echarts' // 注册echarts组件 // 核心插件 Vue.use(d2Admin) Vue.use(VXETable) Vue.prototype.$md5 = md5 Vue.prototype.$util = util Vue.prototype.$websocket = websocket -Vue.prototype.$echarts = echarts //注册echarts组件 +Vue.prototype.$echarts = echarts new Vue({ router, store, diff --git a/web/src/views/dashboard/workbench/components/about.vue b/web/src/views/dashboard/workbench/components/about.vue index 624a268..689f817 100644 --- a/web/src/views/dashboard/workbench/components/about.vue +++ b/web/src/views/dashboard/workbench/components/about.vue @@ -1,6 +1,6 @@ - - - - - \ No newline at end of file diff --git a/web/src/views/dashboard/workbench/components/sumTotal.vue b/web/src/views/dashboard/workbench/components/sumTotal.vue deleted file mode 100644 index 640c0e5..0000000 --- a/web/src/views/dashboard/workbench/components/sumTotal.vue +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/web/src/views/dashboard/workbench/components/time.vue b/web/src/views/dashboard/workbench/components/time.vue index ae5b55c..a53321b 100644 --- a/web/src/views/dashboard/workbench/components/time.vue +++ b/web/src/views/dashboard/workbench/components/time.vue @@ -1,5 +1,5 @@