diff --git a/apps/enm/models.py b/apps/enm/models.py index 0523480f..3426fd93 100644 --- a/apps/enm/models.py +++ b/apps/enm/models.py @@ -1,25 +1,40 @@ from django.db import models -from apps.utils.models import CommonBDModel, BaseModel +from apps.utils.models import CommonBDModel, BaseModel, CommonADModel, CommonAModel, CommonBModel + +class Product(CommonAModel): + """ + 产品 + """ + name = models.CharField('名称', max_length=50) + code = models.CharField('编号', max_length=50, null=True, blank=True) + + class Meta: + verbose_name = '产品' + +class Shift(CommonAModel): + """班次 + """ + name = models.CharField('名称', max_length=50) + start_time_o = models.TimeField('开始时间') + end_time_o = models.TimeField('结束时间') + + class Meta: + verbose_name = '班次' class Mgroup(CommonBDModel): """测点集 """ name = models.CharField('名称', max_length=50) + class Meta: + verbose_name = '测点集' -class Team(CommonBDModel): + +class Team(CommonBModel): """班组 """ name = models.CharField('名称', max_length=50) - members = models.ManyToManyField('system.user', verbose_name='关联成员', through='enm.teammember') - - -class TeamMember(BaseModel): - """班组成员 - """ - team = models.ForeignKey('enm.team', verbose_name='关联班组', on_delete=models.CASCADE) - is_main = models.BooleanField('是否班长', default=False) - member = models.ForeignKey('system.user', verbose_name='关联用户', on_delete=models.CASCADE) + leader = models.ForeignKey('system.user', verbose_name='班长', on_delete=models.CASCADE) class Mpoint(CommonBDModel): @@ -44,7 +59,11 @@ class Mrecord(BaseModel): tag_val = models.FloatField('当前值') -class Drecord(BaseModel): +class Drecord(CommonADModel): """值班记录 """ - team = models.ForeignKey(Team, verbose_name='班组', on_delete=models.CASCADE) \ No newline at end of file + team = models.ForeignKey(Team, verbose_name='班组', on_delete=models.CASCADE) + shit = models.ForeignKey(Shift, verbose_name='当班班次', on_delete=models.CASCADE) + leader = models.ForeignKey('system.user', verbose_name='班长', on_delete=models.CASCADE) + start_time = models.DateTimeField('值班开始') + end_time = models.DateTimeField('值班结束') \ No newline at end of file diff --git a/apps/enm/serializers.py b/apps/enm/serializers.py index fb05d2dd..5ce4138a 100644 --- a/apps/enm/serializers.py +++ b/apps/enm/serializers.py @@ -1,11 +1,41 @@ from apps.utils.serializers import CustomModelSerializer -from apps.enm.models import Mpoint +from apps.enm.models import Mpoint, Mgroup, Mrecord, Team, Drecord +from apps.system.models import Dept +from apps.system.serializers import DeptSimpleSerializer from apps.utils.constants import EXCLUDE_FIELDS, EXCLUDE_FIELDS_BASE from rest_framework import serializers +class MgroupSerializer(CustomModelSerializer): + belong_dept = serializers.PrimaryKeyRelatedField(label="所属部门", queryset=Dept.objects.all(), required=True) + belong_dept_name = serializers.CharField(source='belong_dept.name') + class Meta: + model = Mgroup + fields = '__all__' + read_only_fields = EXCLUDE_FIELDS + ['belong_dept_name'] + +class TeamSerializer(CustomModelSerializer): + leader_name = serializers.CharField(source='leader.name') + belong_dept_name = serializers.CharField(source='belong_dept.name') + class Meta: + model = Team + fields = '__all__' + read_only_fields = EXCLUDE_FIELDS + ['belong_dept_name', 'leader_name'] + class MpointSerializer(CustomModelSerializer): + mgroup_name = serializers.CharField(source='mgroup.name') + belong_dept_name = serializers.CharField(source='belong_dept.name') + ep_monitored_name = serializers.CharField(source='ep_monitored.name') + ep_belong_name = serializers.CharField(source='ep_belong.name') class Meta: model = Mpoint fields = '__all__' - read_only_fields = EXCLUDE_FIELDS \ No newline at end of file + read_only_fields = EXCLUDE_FIELDS + ['mgroup_name', 'belong_dept_name'] + + +class MrecordSerializer(CustomModelSerializer): + mpoint_name = serializers.CharField(source='mpoint.name') + class Meta: + model = Mrecord + fields = '__all__' + read_only_fields = EXCLUDE_FIELDS + ['mpoint_name'] diff --git a/apps/enm/tasks.py b/apps/enm/tasks.py new file mode 100644 index 00000000..b6db1bb9 --- /dev/null +++ b/apps/enm/tasks.py @@ -0,0 +1,15 @@ +# Create your tasks here +from __future__ import absolute_import, unicode_literals +from apps.utils.tasks import CustomTask +from celery import shared_task +from apps.utils.sql import DbConnection +from server.settings import get_sysconfig + +@shared_task(base=CustomTask) +def get_tag_val(): + config = get_sysconfig() + with DbConnection(config['enm']['db_host'], config['enm']['db_user'], config['enm']['db_password'], config['enm']['db_database']) as cursor: + cursor.execute("select * from tag_value") + results = cursor.fetchall() + for row in results: + print(row) \ No newline at end of file diff --git a/apps/enm/urls.py b/apps/enm/urls.py index 24b0ad9c..6f15d882 100644 --- a/apps/enm/urls.py +++ b/apps/enm/urls.py @@ -1,12 +1,15 @@ from django.urls import path, include from rest_framework.routers import DefaultRouter -from apps.enm.views import MpointViewSet +from apps.enm.views import MpointViewSet, MgroupViewSet, TeamViewSet API_BASE_URL = 'api/enm/' HTML_BASE_URL = 'enm/' router = DefaultRouter() router.register('mpoint', MpointViewSet, basename='mpoint') +router.register('mgroup', MgroupViewSet, basename='mgroup') +router.register('team', TeamViewSet, basename='team') + urlpatterns = [ path(API_BASE_URL, include(router.urls)), ] \ No newline at end of file diff --git a/apps/enm/views.py b/apps/enm/views.py index 386e6baf..a23f6718 100644 --- a/apps/enm/views.py +++ b/apps/enm/views.py @@ -1,13 +1,28 @@ from django.shortcuts import render -from apps.enm.models import Mpoint +from apps.enm.models import Mpoint, Mgroup, Team, Mrecord from apps.utils.viewsets import CustomModelViewSet -from apps.enm.serializers import MpointSerializer +from apps.enm.serializers import MpointSerializer, TeamSerializer, MgroupSerializer from rest_framework.exceptions import ParseError +class MgroupViewSet(CustomModelViewSet): + queryset = Mgroup.objects.all() + serializer_class = MgroupSerializer + select_related_fields = ['create_by', 'belong_dept'] + filterset_fields = ['belong_dept'] + search_fields = ['number'] + + +class TeamViewSet(CustomModelViewSet): + queryset = Team.objects.all() + serializer_class = TeamSerializer + select_related_fields = ['belong_dept', 'leader'] + filterset_fields = ['belong_dept'] + search_fields = ['name'] + class MpointViewSet(CustomModelViewSet): queryset = Mpoint.objects.all() serializer_class = MpointSerializer - select_related_fields = ['create_by'] - filterset_fields = ['equipment'] + select_related_fields = ['create_by', 'belong_dept', 'ep_monitored', 'ep_belong', 'mgroup'] + filterset_fields = ['belong_dept', 'ep_monitored', 'ep_belong', 'mgroup'] search_fields = ['number', 'code'] \ No newline at end of file diff --git a/apps/system/views.py b/apps/system/views.py index 7dc89a45..12754009 100755 --- a/apps/system/views.py +++ b/apps/system/views.py @@ -41,7 +41,7 @@ from rest_framework.viewsets import GenericViewSet from cron_descriptor import get_description import locale from drf_yasg.utils import swagger_auto_schema -from server.settings import SYSCONF, SYS_JSON_PATH +from server.settings import get_sysconfig, update_sysconfig # logger.info('请求成功! response_code:{};response_headers:{}; # response_body:{}'.format(response_code, response_headers, response_body[:251])) @@ -653,7 +653,8 @@ class ApkViewSet(MyLoggingMixin, ListModelMixin, CreateModelMixin, GenericViewSe 获取apk信息 """ - return Response({'version': SYSCONF['apk']['apk_version'], 'file': SYSCONF['apk']['apk_file']}) + config = get_sysconfig() + return Response({'version': config['apk']['apk_version'], 'file': config['apk']['apk_file']}) def create(self, request, *args, **kwargs): """ @@ -664,12 +665,12 @@ class ApkViewSet(MyLoggingMixin, ListModelMixin, CreateModelMixin, GenericViewSe sr = ApkSerializer(data=request.data) sr.is_valid(raise_exception=True) vdata = sr.validated_data - from shutil import copyfile - copyfile(settings.BASE_DIR + vdata['file'], settings.BASE_DIR + '/media/zc_ehs.apk') - global SYSCONF - SYSCONF['apk']['apk_version'] = vdata['version'] - SYSCONF['apk']['apk_file'] = vdata['file'] - SysConfigView.save_sysconf() + update_sysconfig({ + "apk":{ + "apk_version": vdata['version'], + "apk_file": vdata['file'] + } + }) return Response() @@ -728,27 +729,12 @@ class SysBaseConfigView(APIView): 获取系统基本信息 """ - base_dict = {key: SYSCONF[key] for key in self.read_keys if key in SYSCONF} + config = get_sysconfig() + base_dict = {key: config[key] for key in self.read_keys if key in config} return Response(base_dict) class SysConfigView(MyLoggingMixin, APIView): perms_map = {'get': 'sysconfig.view', 'put': 'sysconfig.update'} - - def update_dict(self, dict1, dict2): - for key, value in dict2.items(): - if key == 'apk_file': # apk_file拷贝到固定位置 - from shutil import copyfile - copyfile(settings.BASE_DIR + value, settings.BASE_DIR + '/media/zc_ehs.apk') - else: - if key in dict1 and isinstance(dict1[key], dict) and isinstance(value, dict): - self.update_dict(dict1[key], value) - else: - dict1[key] = value - - @staticmethod - def save_sysconf(): - with open(SYS_JSON_PATH, 'wb') as f: - f.write(json.dumps(SYSCONF, indent=4, ensure_ascii=False).encode('utf-8')) def get(self, request, format=None): """ @@ -756,7 +742,7 @@ class SysConfigView(MyLoggingMixin, APIView): 获取config json """ - return Response(SYSCONF) + return Response(get_sysconfig()) @swagger_auto_schema(request_body=Serializer) def put(self, request, format=None): @@ -766,12 +752,5 @@ class SysConfigView(MyLoggingMixin, APIView): 修改config json """ data = request.data - global SYSCONF - old_sysconf = SYSCONF - try: - self.update_dict(SYSCONF, data) - self.save_sysconf() - except: - SYSCONF = old_sysconf - raise + update_sysconfig(data) return Response() \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 27ca1466..4930cfae 100755 --- a/requirements.txt +++ b/requirements.txt @@ -29,3 +29,4 @@ aliyun-python-sdk-core==2.13.36 xlwt==1.3.0 openpyxl==3.1.0 cron-descriptor==1.2.35 +pymysql==1.0.3 diff --git a/server/settings.py b/server/settings.py index eb7fbdcd..ef1f11c2 100755 --- a/server/settings.py +++ b/server/settings.py @@ -14,6 +14,7 @@ from datetime import datetime, timedelta import os import json from . import conf +from django.core.cache import cache # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) @@ -21,13 +22,38 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/ -# 读取配置文件 SYS_JSON_PATH = os.path.join(BASE_DIR, 'server/conf.json') -if not os.path.exists(SYS_JSON_PATH): - raise SystemError('未找到配置文件') -with open(SYS_JSON_PATH, 'r', encoding='utf-8') as f: - SYSCONF = json.loads(f.read()) +def get_sysconfig(reload=False): + config = cache.get('system_config') + if config is None or reload: + # 读取配置文件 + if not os.path.exists(SYS_JSON_PATH): + raise SystemError('未找到配置文件') + with open(SYS_JSON_PATH, 'r', encoding='utf-8') as f: + config = json.loads(f.read()) + cache.set('system_config', config) + return config + return config + +def update_dict(dict1, dict2): + for key, value in dict2.items(): + if key == 'apk_file': # apk_file拷贝到固定位置 + from shutil import copyfile + copyfile(BASE_DIR + value, BASE_DIR + '/media/zc_ehs.apk') + else: + if key in dict1 and isinstance(dict1[key], dict) and isinstance(value, dict): + update_dict(dict1[key], value) + else: + dict1[key] = value + +def update_sysconfig(new_dict): + config = get_sysconfig() + update_dict(config, new_dict) + with open(SYS_JSON_PATH, 'wb') as f: + f.write(json.dumps(config, indent=4, ensure_ascii=False).encode('utf-8')) + cache.set('system_config', config) + # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = conf.SECRET_KEY @@ -172,7 +198,6 @@ EMAIL_HOST = conf.EMAIL_HOST EMAIL_PORT = conf.EMAIL_PORT EMAIL_HOST_USER = conf.EMAIL_HOST_USER EMAIL_HOST_PASSWORD = conf.EMAIL_HOST_PASSWORD -EMAIL_SUBJECT_PREFIX = SYSCONF['base']['base_name_short'] EMAIL_USE_TLS = conf.EMAIL_USE_TLS # 默认主键