diff --git a/backend/application/settings.py b/backend/application/settings.py index 8b2c8c2d79689f2671f77db328dd5648a41f4360..1fc069dbca6fd08d2a98379dce21162897c58e5c 100644 --- a/backend/application/settings.py +++ b/backend/application/settings.py @@ -60,6 +60,7 @@ INSTALLED_APPS = [ "captcha", "channels", "dvadmin.system", + "asset" ] MIDDLEWARE = [ diff --git a/backend/application/urls.py b/backend/application/urls.py index cb5a89997adb091fb3f8b071a6c7be814583e766..1068457b28d931b2604d15cdb5fcf76927503a8b 100644 --- a/backend/application/urls.py +++ b/backend/application/urls.py @@ -99,6 +99,7 @@ urlpatterns = ( name="schema-redoc", ), path("api/system/", include("dvadmin.system.urls")), + path("api/asset/", include("asset.urls")), path("api/login/", LoginView.as_view(), name="token_obtain_pair"), path("api/logout/", LogoutView.as_view(), name="token_obtain_pair"), path("token/refresh/", TokenRefreshView.as_view(), name="token_refresh"), diff --git a/backend/asset/__init__.py b/backend/asset/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/backend/asset/admin.py b/backend/asset/admin.py new file mode 100644 index 0000000000000000000000000000000000000000..8c38f3f3dad51e4585f3984282c2a4bec5349c1e --- /dev/null +++ b/backend/asset/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/backend/asset/apps.py b/backend/asset/apps.py new file mode 100644 index 0000000000000000000000000000000000000000..08b6f71957da5bb67fe748652947a2777b3431f1 --- /dev/null +++ b/backend/asset/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class AssetConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "asset" diff --git a/backend/asset/migrations/__init__.py b/backend/asset/migrations/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/backend/asset/models.py b/backend/asset/models.py new file mode 100644 index 0000000000000000000000000000000000000000..c35d6f22587c2080aa6f424fb4a7b4ec2c674b6c --- /dev/null +++ b/backend/asset/models.py @@ -0,0 +1,115 @@ +from django.db import models + +from common.common_models import CoreModel, TreeNodeModel +from dvadmin.system.models import Users + + +class AssetCategory(TreeNodeModel): + + """ + @author: 陈仕贤 + @contact: QQ:49933729 + @Created on: 2024/6/29 + @Remark: 资产类别 + """ + + number = models.CharField(max_length=50, unique=True, verbose_name="编码", help_text="编码") + name = models.CharField(max_length=250, verbose_name="名称", help_text="名称") + sort = models.IntegerField(default=1, verbose_name="顺序", help_text="顺序") + status = models.BooleanField(default=True, verbose_name="状态", help_text="状态") + + class Meta: + db_table = "asset_category" + verbose_name = "资产类别表" + verbose_name_plural = verbose_name + ordering = ("sort",) + + +class AssetItem(CoreModel): + + """ + @author: 陈仕贤 + @contact: QQ:49933729 + @Created on: 2024/6/29 + @Remark: 资产清单 + """ + + number = models.CharField(max_length=50, unique=True, verbose_name="编码", help_text="编码") + name = models.CharField(max_length=250, verbose_name="名称", help_text="名称") + category = models.ForeignKey(AssetCategory, models.SET_NULL, related_name='asset_item', verbose_name='类别', + null=True) + rfid = models.CharField(max_length=150, verbose_name="RFID", null=True, blank=True) + brand = models.CharField(max_length=150, verbose_name="品牌", null=True, blank=True) + model = models.CharField(max_length=150, verbose_name="型号", null=True, blank=True) + buy_way = models.CharField(max_length=150, verbose_name="购置方式", null=True, blank=True) + buy_time = models.DateTimeField(help_text="购置时间", verbose_name="购置时间", null=True) + buy_price = models.DecimalField(max_digits=10, decimal_places=2, null=True) + admin = models.ForeignKey(Users, models.SET_NULL, related_name='asset_item_admin', verbose_name='管理员', null=True) + user = models.ForeignKey(Users, models.SET_NULL, related_name='asset_item_user', verbose_name='使用人', null=True) + sort = models.IntegerField(default=1, verbose_name="顺序", help_text="顺序") + status = models.BooleanField(default=True, verbose_name="状态", help_text="状态") + + class Meta: + db_table = "asset_item" + verbose_name = "资产清单表" + verbose_name_plural = verbose_name + ordering = ("sort",) + + + + + +class ApplyAbstract(CoreModel): + + """ + @author: 陈仕贤 + @contact: QQ:49933729 + @Created on: 2024/6/30 + @Remark: 申请 + """ + + number = models.CharField(max_length=50, unique=True, verbose_name="编码", help_text="编码") + title = models.CharField(max_length=250, verbose_name="标题", help_text="标题") + remark = models.TextField() + sort = models.IntegerField(default=1, verbose_name="顺序", help_text="顺序") + status = models.BooleanField(default=True, verbose_name="状态", help_text="状态") + + class Meta: + abstract = True + verbose_name = "申请表抽象" + verbose_name_plural = verbose_name + + +class Apply(ApplyAbstract): + + """ + @author: 陈仕贤 + @contact: QQ:49933729 + @Created on: 2024/6/30 + @Remark: 申请 + """ + + class Meta: + db_table = "apply" + verbose_name = "申请表" + verbose_name_plural = verbose_name + ordering = ("number", "title", "remark", "sort", "status") + + +class AssetInApply(ApplyAbstract): + + """ + @author: 陈仕贤 + @contact: QQ:49933729 + @Created on: 2024/6/30 + @Remark: 资产申请 + """ + + handle_time = models.DateTimeField(help_text="处理时间", verbose_name="处理时间", null=True) + num = models.IntegerField(default=1, verbose_name="数量", help_text="数量") + + class Meta: + db_table = "asset_in_apply" + verbose_name = "资产入库申请表" + verbose_name_plural = verbose_name + ordering = ("number", "title", "handle_time", "num", "remark") diff --git a/backend/asset/tests.py b/backend/asset/tests.py new file mode 100644 index 0000000000000000000000000000000000000000..7ce503c2dd97ba78597f6ff6e4393132753573f6 --- /dev/null +++ b/backend/asset/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/backend/asset/urls.py b/backend/asset/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..4689765497410d69af1952657b730dd3c85f3928 --- /dev/null +++ b/backend/asset/urls.py @@ -0,0 +1,14 @@ +from django.urls import path +from rest_framework import routers + +from asset.views.item import ItemViewSet +from asset.views.category import CategoryViewSet + +system_url = routers.SimpleRouter() +system_url.register(r'item', ItemViewSet) +system_url.register(r'category', CategoryViewSet) + +urlpatterns = [] + +urlpatterns += system_url.urls + diff --git a/backend/asset/views.py b/backend/asset/views.py new file mode 100644 index 0000000000000000000000000000000000000000..91ea44a218fbd2f408430959283f0419c921093e --- /dev/null +++ b/backend/asset/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/backend/asset/views/__init__.py b/backend/asset/views/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/backend/asset/views/category.py b/backend/asset/views/category.py new file mode 100644 index 0000000000000000000000000000000000000000..1484272e37780aabe019178c42815e94eadc3896 --- /dev/null +++ b/backend/asset/views/category.py @@ -0,0 +1,65 @@ +""" +@author: 陈仕贤 +@contact: QQ:49933729 +@Created on: 2024/7/02 +@Remark: 资产类别管理 +""" + +from rest_framework.response import Response +from rest_framework import serializers + +from dvadmin.utils.serializers import CustomModelSerializer +from dvadmin.utils.validator import CustomUniqueValidator +from dvadmin.utils.viewset import CustomModelViewSet + +from asset.models import AssetCategory +from dvadmin.utils.json_response import SuccessResponse + + +class CategorySerializer(CustomModelSerializer): + """ + 序列化器 + """ + + + + class Meta: + model = AssetCategory + fields = "__all__" + read_only_fields = ["id"] + + +class CategoryCreateUpdateSerializer(CustomModelSerializer): + """ + 增加或更新的序列化器 + """ + + class Meta: + model = AssetCategory + fields = '__all__' + + +class CategoryViewSet(CustomModelViewSet): + """ + 资产清单管理接口 + list:查询 + create:新增 + update:修改 + retrieve:单例 + destroy:删除 + """ + queryset = AssetCategory.objects.all() + serializer_class = CategorySerializer + create_serializer_class = CategoryCreateUpdateSerializer + update_serializer_class = CategoryCreateUpdateSerializer + search_fields = ['name', 'key'] + + def list(self, request, *args, **kwargs): + queryset = self.filter_queryset(self.get_queryset()) + serializer = self.get_serializer(queryset, many=True, request=request) + return SuccessResponse(data=serializer.data, msg="获取成功") + + + + + diff --git a/backend/asset/views/item.py b/backend/asset/views/item.py new file mode 100644 index 0000000000000000000000000000000000000000..5b2d1090ade5513e622d7b41feca3b4bbca06160 --- /dev/null +++ b/backend/asset/views/item.py @@ -0,0 +1,59 @@ +""" +@author: 陈仕贤 +@contact: QQ:49933729 +@Created on: 2024/6/29 +@Remark: 资产清单管理 +""" + +from rest_framework.response import Response +from rest_framework import serializers + +from dvadmin.utils.serializers import CustomModelSerializer +from dvadmin.utils.validator import CustomUniqueValidator +from dvadmin.utils.viewset import CustomModelViewSet + +from asset.models import AssetItem + + +class ItemSerializer(CustomModelSerializer): + """ + 角色-序列化器 + """ + + class Meta: + model = AssetItem + fields = "__all__" + read_only_fields = ["id"] + + +class ItemCreateUpdateSerializer(CustomModelSerializer): + + # def save(self, **kwargs): + # is_superuser = self.request.user.is_superuser + # if not is_superuser: + # self.validated_data.pop('admin') + # data = super().save(**kwargs) + # return data + + class Meta: + model = AssetItem + fields = '__all__' + + +class ItemViewSet(CustomModelViewSet): + """ + 资产清单管理接口 + list:查询 + create:新增 + update:修改 + retrieve:单例 + destroy:删除 + """ + queryset = AssetItem.objects.all() + serializer_class = ItemSerializer + create_serializer_class = ItemCreateUpdateSerializer + update_serializer_class = ItemCreateUpdateSerializer + search_fields = ['name', 'key'] + + + diff --git a/backend/common/__init__.py b/backend/common/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/backend/common/common_models.py b/backend/common/common_models.py new file mode 100644 index 0000000000000000000000000000000000000000..8067962f08956fe7c32ba829a787c572c71d6c59 --- /dev/null +++ b/backend/common/common_models.py @@ -0,0 +1,175 @@ +""" +@author: 陈仕贤 +@contact: QQ:49933729 +@Created on: 2024-06-30 +@Remark: 公共基础model类 +""" + +from importlib import import_module + +from django.apps import apps +from django.db import models +from django.conf import settings + +from application import settings + +table_prefix = settings.TABLE_PREFIX # 数据库表名前缀 + + +class SoftDeleteQuerySet(models.QuerySet): + pass + + +class SoftDeleteManager(models.Manager): + """支持软删除""" + + def __init__(self, *args, **kwargs): + self.__add_is_del_filter = False + super(SoftDeleteManager, self).__init__(*args, **kwargs) + + def filter(self, *args, **kwargs): + # 考虑是否主动传入is_deleted + if not kwargs.get('is_deleted') is None: + self.__add_is_del_filter = True + return super(SoftDeleteManager, self).filter(*args, **kwargs) + + def get_queryset(self): + if self.__add_is_del_filter: + 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): + return SoftDeleteQuerySet(self.model).get(username=name) + + +class SoftDeleteModel(models.Model): + """ + 软删除模型 + 一旦继承,就将开启软删除 + """ + is_deleted = models.BooleanField(verbose_name="是否软删除", help_text='是否软删除', default=False, db_index=True) + objects = SoftDeleteManager() + + class Meta: + abstract = True + verbose_name = '软删除模型' + verbose_name_plural = verbose_name + + def delete(self, using=None, soft_delete=True, *args, **kwargs): + """ + 重写删除方法,直接开启软删除 + """ + self.is_deleted = True + self.save(using=using) + + +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) + 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="修改时间") + create_datetime = models.DateTimeField(auto_now_add=True, null=True, blank=True, help_text="创建时间", + verbose_name="创建时间") + + class Meta: + abstract = True + verbose_name = '核心模型' + verbose_name_plural = verbose_name + + +class TreeNodeModel(CoreModel): + """ + 树节点的抽象模型模型,可直接继承使用 + 增加父节点ID字段 + """ + parent_id = models.BigIntegerField(help_text="父节点ID", verbose_name="父节点ID") + + class Meta: + abstract = True + verbose_name = '树节点抽象模型' + verbose_name_plural = verbose_name + + + +def get_all_models_objects(model_name=None): + """ + 获取所有 models 对象 + :return: {} + """ + settings.ALL_MODELS_OBJECTS = {} + if not settings.ALL_MODELS_OBJECTS: + all_models = apps.get_models() + for item in list(all_models): + table = { + "tableName": item._meta.verbose_name, + "table": item.__name__, + "tableFields": [] + } + for field in item._meta.fields: + fields = { + "title": field.verbose_name, + "field": field.name + } + table['tableFields'].append(fields) + 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 {} + + +def get_model_from_app(app_name): + """获取模型里的字段""" + model_module = import_module(app_name + '.models') + filter_model = [ + getattr(model_module, item) for item in dir(model_module) + if item != 'CoreModel' and issubclass(getattr(model_module, item).__class__, models.base.ModelBase) + ] + model_list = [] + for model in filter_model: + if model.__name__ == 'AbstractUser': + continue + fields = [ + {'title': field.verbose_name, 'name': field.name, 'object': field} + for field in model._meta.fields + ] + model_list.append({ + 'app': app_name, + 'verbose': model._meta.verbose_name, + 'model': model.__name__, + 'object': model, + 'fields': fields + }) + return model_list + + +def get_custom_app_models(app_name=None): + """ + 获取所有项目下的app里的models + """ + if app_name: + return get_model_from_app(app_name) + all_apps = apps.get_app_configs() + res = [] + for app in all_apps: + if app.name.startswith('django'): + continue + if app.name in settings.COLUMN_EXCLUDE_APPS: + continue + try: + all_models = get_model_from_app(app.name) + if all_models: + for model in all_models: + res.append(model) + except Exception as e: + pass + return res diff --git a/backend/dvadmin/__init__.py b/backend/dvadmin/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..40a96afc6ff09d58a702b76e3f7dd412fe975e26 --- /dev/null +++ b/backend/dvadmin/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/backend/dvadmin/system/fixtures/init_menu.json b/backend/dvadmin/system/fixtures/init_menu.json index 425887234ac2af9b6d904e786b969173c8e27729..b683f0af73fb39e6746918b0b0f3c8f05ff17a8f 100644 --- a/backend/dvadmin/system/fixtures/init_menu.json +++ b/backend/dvadmin/system/fixtures/init_menu.json @@ -167,19 +167,13 @@ "method": 0 }, { - "name": "查询所有", + "name": "获取所有部门", "value": "dept:SearchAll", "api": "/api/system/dept/all_dept/", "method": 0 }, { - "name": "懒加载查询所有", - "value": "dept:LazySearchAll", - "api": "/api/system/dept/dept_lazy_tree/", - "method": 0 - }, - { - "name": "头信息", + "name": "部门顶部信息", "value": "dept:HeaderInfo", "api": "/api/system/dept/dept_info/", "method": 0 diff --git a/backend/dvadmin/system/views/dept.py b/backend/dvadmin/system/views/dept.py index 5c5105b7fe2dbbae14249d15ce86d6e1005f8c48..de48b0dbba652a91ceeadf47c9738ddc2345f5c0 100644 --- a/backend/dvadmin/system/views/dept.py +++ b/backend/dvadmin/system/views/dept.py @@ -10,6 +10,7 @@ from rest_framework.decorators import action from rest_framework.permissions import IsAuthenticated from dvadmin.system.models import Dept, RoleMenuButtonPermission, Users +from dvadmin.utils.filters import DataLevelPermissionsFilter from dvadmin.utils.json_response import DetailResponse, SuccessResponse, ErrorResponse from dvadmin.utils.serializers import CustomModelSerializer from dvadmin.utils.viewset import CustomModelViewSet @@ -124,33 +125,7 @@ class DeptViewSet(CustomModelViewSet): data = serializer.data return SuccessResponse(data=data) - @action(methods=["GET"], detail=False, permission_classes=[IsAuthenticated], extra_filter_class=[]) - def dept_lazy_tree(self, request, *args, **kwargs): - parent = self.request.query_params.get('parent') - is_superuser = request.user.is_superuser - if is_superuser: - queryset = Dept.objects.values('id', 'name', 'parent') - else: - role_ids = request.user.role.values_list('id', flat=True) - data_range = RoleMenuButtonPermission.objects.filter(role__in=role_ids).values_list('data_range', flat=True) - user_dept_id = request.user.dept.id - dept_list = [user_dept_id] - data_range_list = list(set(data_range)) - for item in data_range_list: - if item in [0, 2]: - dept_list = [user_dept_id] - elif item == 1: - dept_list = Dept.recursion_all_dept(dept_id=user_dept_id) - elif item == 3: - dept_list = Dept.objects.values_list('id', flat=True) - elif item == 4: - dept_list = request.user.role.values_list('dept', flat=True) - else: - dept_list = [] - queryset = Dept.objects.filter(id__in=dept_list).values('id', 'name', 'parent') - return DetailResponse(data=queryset, msg="获取成功") - - @action(methods=["GET"], detail=False, permission_classes=[IsAuthenticated], extra_filter_class=[]) + @action(methods=["GET"], detail=False, permission_classes=[IsAuthenticated]) def all_dept(self, request, *args, **kwargs): queryset = self.filter_queryset(self.get_queryset()) data = queryset.filter(status=True).order_by('sort').values('name', 'id', 'parent') diff --git a/backend/dvadmin/system/views/menu_button.py b/backend/dvadmin/system/views/menu_button.py index f91839a8d794737af6ea73aef0f8e4b82d124cac..f6cc411f291503204f699a68fa606706f1e5bcd4 100644 --- a/backend/dvadmin/system/views/menu_button.py +++ b/backend/dvadmin/system/views/menu_button.py @@ -10,7 +10,7 @@ from django.db.models import F from rest_framework.decorators import action from rest_framework.permissions import IsAuthenticated -from dvadmin.system.models import MenuButton, RoleMenuButtonPermission +from dvadmin.system.models import MenuButton, RoleMenuButtonPermission, Menu from dvadmin.utils.json_response import DetailResponse, SuccessResponse from dvadmin.utils.serializers import CustomModelSerializer from dvadmin.utils.viewset import CustomModelViewSet diff --git a/backend/dvadmin/system/views/role_menu_button_permission.py b/backend/dvadmin/system/views/role_menu_button_permission.py index 604ebe24c0cbfe6cb35f6420a5ad63ef8079de64..d44fab2b547d7e1380003293f521a6a1a3e327c2 100644 --- a/backend/dvadmin/system/views/role_menu_button_permission.py +++ b/backend/dvadmin/system/views/role_menu_button_permission.py @@ -180,51 +180,16 @@ class RoleMenuButtonPermissionViewSet(CustomModelViewSet): :return: menu,btns,columns """ params = request.query_params - role = params.get('role', None) - if role is None: - return ErrorResponse(msg="未获取到角色信息") is_superuser = request.user.is_superuser if is_superuser: queryset = Menu.objects.filter(status=1, is_catalog=True).values('name', 'id').all() else: role_id = request.user.role.values_list('id', flat=True) - menu_list = RoleMenuPermission.objects.filter(role__in=role_id).values_list('id', flat=True) + menu_list = RoleMenuPermission.objects.filter(role__in=role_id).values_list('menu__id', flat=True) queryset = Menu.objects.filter(status=1, is_catalog=True, id__in=menu_list).values('name', 'id').all() serializer = RoleMenuSerializer(queryset, many=True, request=request) data = serializer.data return DetailResponse(data=data) - # data = [] - # if is_superuser: - # queryset = Menu.objects.filter(status=1, is_catalog=False).values('name', 'id').all() - # else: - # role_id = request.user.role.values_list('id', flat=True) - # menu_list = RoleMenuPermission.objects.filter(role__in=role_id).values_list('id', flat=True) - # queryset = Menu.objects.filter(status=1, is_catalog=False, id__in=menu_list).values('name', 'id') - # for item in queryset: - # parent_list = Menu.get_all_parent(item['id']) - # names = [d["name"] for d in parent_list] - # completeName = "/".join(names) - # isCheck = RoleMenuPermission.objects.filter( - # menu__id=item['id'], - # role__id=role, - # ).exists() - # mbCheck = RoleMenuButtonPermission.objects.filter( - # menu_button=OuterRef("pk"), - # role__id=role, - # ) - # btns = MenuButton.objects.filter( - # menu__id=item['id'], - # ).annotate(isCheck=Exists(mbCheck)).values('id', 'name', 'value', 'isCheck', - # data_range=F('menu_button_permission__data_range')) - # dicts = { - # 'name': completeName, - # 'id': item['id'], - # 'isCheck': isCheck, - # 'btns': btns, - # - # } - # data.append(dicts) - # return DetailResponse(data=data) @action(methods=['PUT'], detail=True, permission_classes=[IsAuthenticated]) def set_role_premission(self, request, pk): diff --git a/backend/dvadmin/system/views/user.py b/backend/dvadmin/system/views/user.py index c6c002e8817abb75a52e8dea166bbf200f51cfdb..fca29333e793c7d8612107451b84e0a55bb4f2de 100644 --- a/backend/dvadmin/system/views/user.py +++ b/backend/dvadmin/system/views/user.py @@ -10,7 +10,7 @@ from django.db.models import Q from application import dispatch from dvadmin.system.models import Users, Role, Dept from dvadmin.system.views.role import RoleSerializer -from dvadmin.utils.json_response import ErrorResponse, DetailResponse, SuccessResponse +from dvadmin.utils.json_response import ErrorResponse, DetailResponse, SuccessResponse, ListResponse from dvadmin.utils.serializers import CustomModelSerializer from dvadmin.utils.validator import CustomUniqueValidator from dvadmin.utils.viewset import CustomModelViewSet @@ -62,6 +62,19 @@ class UserSerializer(CustomModelSerializer): return serializer.data +class UserListSimpleSerializer(CustomModelSerializer): + """ + 用户管理-序列化器 + """ + dept_name = serializers.CharField(source='dept.name', read_only=True) + + class Meta: + model = Users + read_only_fields = ["id"] + exclude = ["password"] + + + class UserCreateSerializer(CustomModelSerializer): """ 用户新增-序列化器 @@ -119,7 +132,6 @@ class UserUpdateSerializer(CustomModelSerializer): """ 更改激活状态 """ - print(111, value) if value: self.initial_data["login_error_count"] = 0 return value @@ -233,6 +245,7 @@ class UserViewSet(CustomModelViewSet): serializer_class = UserSerializer create_serializer_class = UserCreateSerializer update_serializer_class = UserUpdateSerializer + list_simple_serializer_class = UserListSimpleSerializer filter_fields = ["name", "username", "gender", "is_active", "dept", "user_type"] search_fields = ["username", "name", "dept__name", "role__name"] # 导出 @@ -271,6 +284,13 @@ class UserViewSet(CustomModelViewSet): "role": {"title": "角色", "choices": {"queryset": Role.objects.filter(status=True), "values_name": "name"}}, } + @action(methods=["GET"], detail=False) + def list_simple(self, request): + queryset = self.get_queryset() + serializer_class = self.get_serializer_class() + serializer = serializer_class(queryset, many=True) + return ListResponse(data=serializer.data, msg="获取成功") + @action(methods=["GET"], detail=False, permission_classes=[IsAuthenticated]) def user_info(self, request): """获取当前用户信息""" @@ -407,9 +427,12 @@ class UserViewSet(CustomModelViewSet): queryset = self.filter_queryset(self.get_queryset()) else: queryset = self.filter_queryset(self.get_queryset()) + # print(queryset.values('id','name','dept__id')) page = self.paginate_queryset(queryset) if page is not None: serializer = self.get_serializer(page, many=True, request=request) + # print(serializer.data) return self.get_paginated_response(serializer.data) serializer = self.get_serializer(queryset, many=True, request=request) + return SuccessResponse(data=serializer.data, msg="获取成功") diff --git a/backend/dvadmin/utils/json_response.py b/backend/dvadmin/utils/json_response.py index 0d6c363753cd6a4e79668a3658123c7ecc9bd2b8..0a8653e84f9564a7d2f3678b6935a92057dad5a3 100644 --- a/backend/dvadmin/utils/json_response.py +++ b/backend/dvadmin/utils/json_response.py @@ -59,3 +59,20 @@ class ErrorResponse(Response): "msg": msg } super().__init__(std_data, status, template_name, headers, exception, content_type) + + +class ListResponse(Response): + """ + 标准响应成功的返回, SuccessResponse(data)或者SuccessResponse(data=data) + (1)默认code返回2000, 不支持指定其他返回码 + """ + + def __init__(self, data=None, msg='success', status=None, template_name=None, headers=None, exception=False, + content_type=None,page=1,limit=1,total=1): + std_data = { + "code": 2000, + "data": data, + "msg": msg + } + super().__init__(std_data, status, template_name, headers, exception, content_type) + diff --git a/backend/main.py b/backend/main.py index 2408243cdb5fc1c9320565f1d680df38a0c3194e..e0c1aea3cf2efe4e9a0f4d155aa1bae84987e141 100644 --- a/backend/main.py +++ b/backend/main.py @@ -9,5 +9,9 @@ from application.settings import LOGGING if __name__ == '__main__': multiprocessing.freeze_support() - uvicorn.run("application.asgi:application", reload=False, host="0.0.0.0", port=8000, workers=4, + workers = 4 + if os.sys.platform.startswith('win'): + # Windows操作系统 + workers = None + uvicorn.run("application.asgi:application", reload=False, host="0.0.0.0", port=8088, workers=workers, log_config=LOGGING) diff --git a/backend/requirements.txt b/backend/requirements.txt index 6309e7c11080e7c0871da7f9e40d5dd206f9e52e..2e7c6cb6131855497d1be97d0b97f21a4e6eea7c 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -1,6 +1,6 @@ Django==4.2.7 django-comment-migrate==0.1.7 -django-cors-headers==4.3.0 +django-cors-headers==4.4.0 django-filter==23.3 django-ranged-response==0.2.0 djangorestframework==3.14.0 diff --git a/backend/static/logo.icns b/backend/static/logo.icns new file mode 100644 index 0000000000000000000000000000000000000000..99572efcb34019f76a56baed454a7900e63505bf Binary files /dev/null and b/backend/static/logo.icns differ diff --git a/backend/tests/import.xlsx b/backend/tests/import.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..3e53acb74ea20ea72e2aaa656f0e6298be9c659e Binary files /dev/null and b/backend/tests/import.xlsx differ diff --git a/backend/tests/import_asset_category.py b/backend/tests/import_asset_category.py new file mode 100644 index 0000000000000000000000000000000000000000..8ebf1f5b5de25ec823eb2dc7bd043729f64e68cb --- /dev/null +++ b/backend/tests/import_asset_category.py @@ -0,0 +1,66 @@ +from conf.env import DATABASE_HOST, DATABASE_USER, DATABASE_PASSWORD, DATABASE_NAME +import MySQLdb + +import openpyxl + +# 建立连接 +conn = MySQLdb.connect( + host=DATABASE_HOST, # 数据库主机地址 + user=DATABASE_USER, # 数据库用户名 + password=DATABASE_PASSWORD, # 数据库密码 + db=DATABASE_NAME # 数据库名称 +) + +cursor = conn.cursor() + +workbook = openpyxl.load_workbook('./import.xlsx') +table = workbook[workbook.sheetnames[0]] +tableValues = table.values + +def find_id_by_name(name): + cursor.execute('select id from asset_category where name=%s', (name,)) + res = cursor.fetchone() + if not res: + return 0 + return res[0] + + +for index, row in enumerate(tableValues): + if index == 0: + continue + + number = row[0] + name = row[1] + parent_name = row[2] + parent_id = find_id_by_name(parent_name) + sort = row[3] + + param = (number, name, parent_id, sort, 0, 1, ) + + cursor.execute(""" + insert into asset_category(number, name, parent_id, sort, status, creator_id, update_datetime, create_datetime, modifier) + values(%s, %s, %s, %s, %s, %s, now(), now(), 1) + """, param) + + print(row) + +conn.commit() + +# res = find_id_by_name("戴尔台式机") +# print(res) + + + + + + + + + + + + + + + + diff --git "a/backend/\346\225\260\346\215\256\345\272\223\350\277\201\347\247\273.bat" "b/backend/\346\225\260\346\215\256\345\272\223\350\277\201\347\247\273.bat" new file mode 100644 index 0000000000000000000000000000000000000000..3bfa9deec55a857da101e5f10cd2e804d0fb202e --- /dev/null +++ "b/backend/\346\225\260\346\215\256\345\272\223\350\277\201\347\247\273.bat" @@ -0,0 +1,2 @@ +python manage.py makemigrations asset +python manage.py migrate asset \ No newline at end of file diff --git a/docker_env/nginx/my-80.conf b/docker_env/nginx/my-80.conf index e50bdc4697cbe418cc227e1b9e7fe55b334e6322..98d33bd98b9c50792e91a431f43a7ad6996a575d 100644 --- a/docker_env/nginx/my-80.conf +++ b/docker_env/nginx/my-80.conf @@ -7,6 +7,10 @@ server { index index.html index.htm; root /usr/share/nginx/html; try_files $uri $uri/ /index.html; + # 禁止缓存html文件,避免前端页面不及时更新,需要用户手动刷新的情况 + if ($request_uri ~* "^/$|^/index.html|^/index.htm") { + add_header Cache-Control "no-store"; + } } location ~ ^/api/ { diff --git a/docker_env/nginx/my.conf b/docker_env/nginx/my.conf index 178d9793e1db511bc38ee372c104be6ffaacc14e..dd6b3337a19eb93ffdc786635c11995a823a1b06 100644 --- a/docker_env/nginx/my.conf +++ b/docker_env/nginx/my.conf @@ -11,6 +11,10 @@ server { real_ip_header X-Forwarded-For; root /usr/share/nginx/html; index index.html index.php index.htm; + # 禁止缓存html文件,避免前端页面不及时更新,需要用户手动刷新的情况 + if ($request_uri ~* "^/$|^/index.html|^/index.htm") { + add_header Cache-Control "no-store"; + } } location /api/ { diff --git a/sql/asset_category.sql b/sql/asset_category.sql new file mode 100644 index 0000000000000000000000000000000000000000..9e2cc6bb2a1fd7c69fb7e615783d3c6747fb0595 --- /dev/null +++ b/sql/asset_category.sql @@ -0,0 +1,84 @@ +/* + Navicat Premium Data Transfer + + Source Server : 本地 + Source Server Type : MySQL + Source Server Version : 80035 + Source Host : localhost:3306 + Source Schema : asset + + Target Server Type : MySQL + Target Server Version : 80035 + File Encoding : 65001 + + Date: 04/07/2024 09:43:03 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for asset_category +-- ---------------------------- +DROP TABLE IF EXISTS `asset_category`; +CREATE TABLE `asset_category` ( + `id` bigint(0) NOT NULL AUTO_INCREMENT, + `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `modifier` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `dept_belong_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `update_datetime` datetime(6) NULL DEFAULT NULL, + `create_datetime` datetime(6) NULL DEFAULT NULL, + `parent_id` bigint(0) NOT NULL, + `number` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `name` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `sort` int(0) NULL DEFAULT NULL, + `status` tinyint(1) NOT NULL, + `creator_id` bigint(0) NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `number`(`number`) USING BTREE, + INDEX `asset_category_creator_id_f275c846`(`creator_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 155 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of asset_category +-- ---------------------------- +INSERT INTO `asset_category` VALUES (117, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 0, '01', '计算机和网络设备', 1, 0, 1); +INSERT INTO `asset_category` VALUES (118, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 117, '0101', '笔记本', 1, 0, 1); +INSERT INTO `asset_category` VALUES (119, NULL, '1', NULL, '2024-07-03 17:45:57.697668', '2024-07-03 09:35:01.000000', 117, '1234', '二手机器', 0, 0, 1); +INSERT INTO `asset_category` VALUES (120, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 117, '0102', '台式机', 2, 0, 1); +INSERT INTO `asset_category` VALUES (121, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 117, '0103', '一体机', 3, 0, 1); +INSERT INTO `asset_category` VALUES (122, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 117, '0104', '主机', 4, 0, 1); +INSERT INTO `asset_category` VALUES (123, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 117, '0105', '显示器', 5, 0, 1); +INSERT INTO `asset_category` VALUES (124, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 117, '0106', '路由器', 6, 0, 1); +INSERT INTO `asset_category` VALUES (125, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 117, '0107', '手机', 7, 0, 1); +INSERT INTO `asset_category` VALUES (126, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 117, '0108', '平板', 8, 0, 1); +INSERT INTO `asset_category` VALUES (127, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 117, '0109', '其它网络设备', 9, 0, 1); +INSERT INTO `asset_category` VALUES (128, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 0, '02', '办公设备', 2, 0, 1); +INSERT INTO `asset_category` VALUES (129, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 128, '0201', '打印机', 1, 0, 1); +INSERT INTO `asset_category` VALUES (130, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 128, '0202', '投影仪', 2, 0, 1); +INSERT INTO `asset_category` VALUES (131, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 128, '0203', 'LED显示屏', 3, 0, 1); +INSERT INTO `asset_category` VALUES (132, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 128, '0204', '标签机', 4, 0, 1); +INSERT INTO `asset_category` VALUES (133, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 128, '0205', '会计器具', 5, 0, 1); +INSERT INTO `asset_category` VALUES (134, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 128, '0206', '其它办公设备', 6, 0, 1); +INSERT INTO `asset_category` VALUES (135, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 0, '03', '办公家具', 3, 0, 1); +INSERT INTO `asset_category` VALUES (136, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 135, '0301', '桌子', 1, 0, 1); +INSERT INTO `asset_category` VALUES (137, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 135, '0302', '椅子', 2, 0, 1); +INSERT INTO `asset_category` VALUES (138, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 135, '0303', '沙发', 3, 0, 1); +INSERT INTO `asset_category` VALUES (139, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 135, '0304', '文件柜', 4, 0, 1); +INSERT INTO `asset_category` VALUES (140, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 135, '0305', '保险柜', 5, 0, 1); +INSERT INTO `asset_category` VALUES (141, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 135, '0306', '其它办公家具', 6, 0, 1); +INSERT INTO `asset_category` VALUES (142, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 0, '04', '办公电器', 4, 0, 1); +INSERT INTO `asset_category` VALUES (143, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 142, '0401', '空调', 1, 0, 1); +INSERT INTO `asset_category` VALUES (144, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 142, '0402', '冰箱冰柜', 2, 0, 1); +INSERT INTO `asset_category` VALUES (145, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 142, '0403', '饮水机', 3, 0, 1); +INSERT INTO `asset_category` VALUES (146, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 142, '0404', '热水器', 4, 0, 1); +INSERT INTO `asset_category` VALUES (147, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 142, '0405', '烹调电器', 5, 0, 1); +INSERT INTO `asset_category` VALUES (148, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 142, '0406', '灯具', 6, 0, 1); +INSERT INTO `asset_category` VALUES (149, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 142, '0407', '其它办公电器', 7, 0, 1); +INSERT INTO `asset_category` VALUES (150, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 0, '05', '文艺体育设备', 5, 0, 1); +INSERT INTO `asset_category` VALUES (151, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 0, '06', '仪器仪表', 6, 0, 1); +INSERT INTO `asset_category` VALUES (152, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 0, '07', '车辆', 7, 0, 1); +INSERT INTO `asset_category` VALUES (153, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 0, '08', '图书、档案', 8, 0, 1); +INSERT INTO `asset_category` VALUES (154, NULL, '1', NULL, '2024-07-03 09:35:01.000000', '2024-07-03 09:35:01.000000', 0, '09', '专用设备', 9, 0, 1); + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/sql/asset_item.sql b/sql/asset_item.sql new file mode 100644 index 0000000000000000000000000000000000000000..4e77edd5b5660b6f87c5e215d5bf7831f3682abd --- /dev/null +++ b/sql/asset_item.sql @@ -0,0 +1,63 @@ +/* + Navicat Premium Data Transfer + + Source Server : 本地 + Source Server Type : MySQL + Source Server Version : 80035 + Source Host : localhost:3306 + Source Schema : asset + + Target Server Type : MySQL + Target Server Version : 80035 + File Encoding : 65001 + + Date: 04/07/2024 09:42:49 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for asset_item +-- ---------------------------- +DROP TABLE IF EXISTS `asset_item`; +CREATE TABLE `asset_item` ( + `id` bigint(0) NOT NULL AUTO_INCREMENT, + `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `modifier` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `dept_belong_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `update_datetime` datetime(6) NULL DEFAULT NULL, + `create_datetime` datetime(6) NULL DEFAULT NULL, + `number` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `name` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `rfid` varchar(150) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `brand` varchar(150) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `model` varchar(150) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `buy_way` varchar(150) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `buy_time` datetime(6) NULL DEFAULT NULL, + `buy_price` decimal(10, 2) NULL DEFAULT NULL, + `sort` int(0) NOT NULL, + `status` tinyint(1) NOT NULL, + `admin_id` bigint(0) NULL DEFAULT NULL, + `category_id` bigint(0) NULL DEFAULT NULL, + `creator_id` bigint(0) NULL DEFAULT NULL, + `user_id` bigint(0) NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `number`(`number`) USING BTREE, + INDEX `asset_item_admin_id_1a6cd17b_fk_dvadmin_system_users_id`(`admin_id`) USING BTREE, + INDEX `asset_item_category_id_1b0617ac_fk_asset_category_id`(`category_id`) USING BTREE, + INDEX `asset_item_user_id_77b9cfa7_fk_dvadmin_system_users_id`(`user_id`) USING BTREE, + INDEX `asset_item_creator_id_9094a9ca`(`creator_id`) USING BTREE, + CONSTRAINT `asset_item_admin_id_1a6cd17b_fk_dvadmin_system_users_id` FOREIGN KEY (`admin_id`) REFERENCES `dvadmin_system_users` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT, + CONSTRAINT `asset_item_category_id_1b0617ac_fk_asset_category_id` FOREIGN KEY (`category_id`) REFERENCES `asset_category` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT, + CONSTRAINT `asset_item_user_id_77b9cfa7_fk_dvadmin_system_users_id` FOREIGN KEY (`user_id`) REFERENCES `dvadmin_system_users` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT +) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of asset_item +-- ---------------------------- +INSERT INTO `asset_item` VALUES (3, NULL, '1', '1', '2024-07-04 09:00:10.679010', '2024-07-04 08:28:01.107255', '4334', '测试资产', NULL, '戴尔', 'X', '采购', '2024-07-25 16:00:00.000000', 100.63, 1, 1, NULL, 135, 1, NULL); +INSERT INTO `asset_item` VALUES (4, NULL, '1', '1', '2024-07-04 09:38:56.559647', '2024-07-04 09:27:42.994190', 'ZC-00020', '实验室专用油性笔', NULL, '', '', '采购', NULL, NULL, 1, 1, NULL, 154, 1, NULL); +INSERT INTO `asset_item` VALUES (5, NULL, '1', '1', '2024-07-04 09:38:18.528205', '2024-07-04 09:38:18.528205', 'ZC-00019', '大功率天线', NULL, '', '', '采购', NULL, NULL, 1, 1, NULL, 154, 1, NULL); + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/web/.env.development b/web/.env.development index 1c3ca5db362e1f7935aded834e08f0a46ed640a6..714c5f5c7d4462f0aabb83c6e468f0e31c5a5543 100644 --- a/web/.env.development +++ b/web/.env.development @@ -2,7 +2,7 @@ ENV = 'development' # 本地环境接口地址 -VITE_API_URL = 'http://127.0.0.1:8000' +VITE_API_URL = 'http://127.0.0.1:8088' # 是否启用按钮权限 VITE_PM_ENABLED = true diff --git a/web/.gitignore b/web/.gitignore index aa1baf223b2cc0a3f75b7a01f6792b7c780de240..8cef9186824172b87665ec830e8e4483b0fd0885 100644 --- a/web/.gitignore +++ b/web/.gitignore @@ -21,3 +21,5 @@ pnpm-debug.log* *.njsproj *.sln *.sw? +# 构建版本文件,无需上传git +public/version-build diff --git a/web/README.zh.md b/web/README.zh.md new file mode 100644 index 0000000000000000000000000000000000000000..2257d975ea9fd8598387c9af721e837624ca4ae6 --- /dev/null +++ b/web/README.zh.md @@ -0,0 +1,68 @@ +# 资产管理系统 - 前端 + + + +💡 **「关于」** + +这是资产管理系统的前端 + + +## 平台简介 + +💡 资产管理系统是一个物联网平台系统,前后端分离, +后端采用django + django-rest-framework, +前端采用基于 vue3 + CompositionAPI + typescript + vite + element plus + + +#### 🏭 环境支持 + +| Edge | Firefox | Chrome | Safari | +| --------- | ------------ | ----------- | ----------- | +| Edge ≥ 79 | Firefox ≥ 78 | Chrome ≥ 64 | Safari ≥ 12 | + +> 不支持 IE11,请升级Edge使用本系统。 + + +## 技术文档 + +- [DVAdmin官网](https://www.django-vue-admin.com) + + +## 源码地址 + +gitee地址(主推):[https://gitee.com/huge-dream/django-vue3-admin](https://gitee.com/huge-dream/django-vue3-admin)👩👦👦 + + +## 准备工作 +~~~ +Python >= 3.11.0 (最低3.9+版本) +nodejs >= 16.0 +Mysql >= 8.0 (可选,默认数据库sqlite3,支持5.7+,推荐8.0版本) +Redis (可选,最新版) +~~~ + +## 安装♝ + +```bash +# 克隆项目 +git clone https://gitee.com/huge-dream/django-vue3-admin.git + +# 进入项目目录 +cd web + +# 安装依赖 +npm install yarn +yarn install --registry=https://registry.npm.taobao.org + +# 启动服务 +yarn build +# 浏览器访问 http://localhost:8080 +# .env.development 文件中可配置启动端口等参数 +# 构建生产环境 +# yarn run build +``` + +### 访问项目 + +- 访问地址:[http://localhost:8080](http://localhost:8080) (默认为此地址,如有修改请按照配置文件) +- 账号:`superadmin` 密码:`admin123456` diff --git a/web/index.html b/web/index.html index 9515e84b71affad9064130809ddf03581b3cf9cc..3e63bed9b7eada8589c0157f84514e0d92b03f63 100644 --- a/web/index.html +++ b/web/index.html @@ -6,26 +6,27 @@ - -