Kaynağa Gözat

Merge branch 'dev' of http://192.168.136.99:3000/SERVER/AnsjerServer into dev

chanjunkai 5 yıl önce
ebeveyn
işleme
66143fe078

+ 31 - 0
Ansjer/config.py

@@ -126,3 +126,34 @@ FCM_CONFIG = {
     'com.ansjer.accloud_a': 'AAAAb9YP3rk:APA91bFm06w8b9OKQ0gz0iaWFuRqRIkvgAz6z7Gp3dBU_X-LNGJQd1hc1QR2W7QzBglF8SHtERA45a2lbdLRa5qv7hxfd6W_sJLBK7dA8jklsOQBvy505oUzTwMKWy4TwH-exps9KrhO',
     'com.ansjer.zccloud_ab': 'AAAAb9YP3rk:APA91bHu8u-CTpcd0g6lKPo0WNVqCi8jZub1cPPbSAY9AucT1HxlF65ZDUko9iG8q2ch17bwu9YWHpK1xI1gHSRXCslLvZlXEmHZC0AG3JKg15XuUvlFKACIajUFV-pOeGRT8tM6-31I',
 }
+
+DEVICE_TYPE = {
+    0: 'UNKOWN',
+    1: 'DVR',
+    2: 'NVR',
+    3: 'POENVR',
+    4: 'WIRELESSNVR',
+    5: 'POEIPC',
+    6: 'BOLTIPC',
+    7: 'IPC',
+    8: 'KAPIANJI',
+    9: 'FISHEYE',
+    10: 'C512',
+    11: 'C611',
+    12: 'C612',
+    13: 'C199',
+    14: 'C190',
+    15: 'C199_PRO',
+    10001: 'DVRPTZ'
+}
+
+APP_FREQUENT = {
+    0: 'UNKOWN',
+    1: '每天',
+    2: '三天',
+    3: '一周',
+    4: '两周',
+    5: '一个月',
+    6: '一个月以上',
+
+}

+ 15 - 3
Ansjer/urls.py

@@ -3,12 +3,14 @@ from django.urls import path, re_path
 
 from Controller import FeedBack, EquipmentOTA, EquipmentInfo, AdminManage, AppInfo, \
     AccessLog, DynamoDBLog, Test, MealManage, DeviceManage, EquipmentStatus, SysManage, DeviceLog, LogAccess, \
-    AppColophon, DateController,\
+    AppColophon, DateController, \
     EquipmentManager, LogManager, PermissionManager, OTAEquipment, shareUserPermission, UidSetController, \
     UserManger, CheckUserData, \
     UserController, CloudVod, OrderContrller, VodBucket, DetectController, DeviceShare, UserBrandController, \
-    StsOssController, UIDPreview, OssCrd, SysMsg, UidUser, EquipmentManagerV2,EquipmentManagerV3, PushDeploy, AppSetController,\
-    ApplicationController, UserExController, CloudStorage, TestApi
+    StsOssController, UIDPreview, OssCrd, SysMsg, UidUser, EquipmentManagerV2, EquipmentManagerV3, PushDeploy, \
+    AppSetController, \
+    ApplicationController, UserExController, CloudStorage, TestApi, UserBrandControllerV2, \
+    StatisticsController
 
 urlpatterns = [
     url(r'^testApi/(?P<operation>.*)$', TestApi.testView.as_view()),
@@ -120,6 +122,11 @@ urlpatterns = [
     url(r'^v2/account/logout$', UserController.V2LogoutView.as_view()),
     url(r'^v2/account/login$', UserController.v3LoginView.as_view()),
     url(r'^v3/account/login$', UserController.v3LoginView.as_view()),
+
+    # 验证码登录
+    url(r'^account/loginCode$', UserController.loginCodeView.as_view()),
+    url(r'^v3/account/loginByCode$', UserController.v3LoginByCodeView.as_view()),
+
     # 新增
     url(r'^detect/detect_group_push$',DetectController.NotificationView.detect_group_push),
     url(r'^detect/add$', DetectController.PushNotificationView.as_view()),
@@ -203,6 +210,11 @@ urlpatterns = [
     url(r'^date/(?P<operation>.*)$', DateController.DateConView.as_view()),
 
     url(r'^equipment/flow_test$', EquipmentManager.uid_status_test),
+    url(r'^account/appFrequency/(?P<operation>.*)$', UserController.UserAppFrequencyView.as_view()),
+    url(r'^v2/userbrand/(?P<operation>.*)$', UserBrandControllerV2.UserBrandV2.as_view()),
+    # url(r'^test/add$', GenerateDataController.GenerateDataView.as_view()),
+    url(r'^statistcs/appFrequencyMonth$', StatisticsController.statistcsAppFrequency),
+    url(r'^statistcs/appFrequencyYear$', StatisticsController.statistcsAppFrequencyYear),
     # app 设备消息模板
     # 路由加参数参考
     # url(r'^(?P<path>.*)/(?P<UID>.*)/lls$', Test.Test.as_view(), name=u'gg'),

+ 215 - 2
Controller/AdminManage.py

@@ -1,16 +1,20 @@
 # -*- coding: utf-8 -*-
+import time
+
+from django.db.models import Count,Q
 from django.views.decorators.csrf import csrf_exempt
 from django.views.generic import TemplateView
 from django.utils.decorators import method_decorator
 from django.contrib.auth.hashers import make_password  # 对密码加密模块
-from Model.models import Device_Info, Role, UserExModel
+from Model.models import Device_Info, Role, UserExModel, User_Brand, UidSetModel, UserAppFrequencyModel, \
+    AppFrequencyStatisticsModel, AppFrequencyYearStatisticsModel
 from Service.ModelService import ModelService
 from django.utils import timezone
 from Model.models import Access_Log, Device_User
 from django.views.decorators.http import require_http_methods
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
-from Ansjer.config import OFF_LINE_TIME_DELTA
+from Ansjer.config import OFF_LINE_TIME_DELTA, DEVICE_TYPE
 import datetime, simplejson as json
 from Service.CommonService import CommonService
 from Object.RedisObject import RedisObject
@@ -64,6 +68,16 @@ class AdminManage(TemplateView):
             return self.getAllUID(userID, response)
         if operation == 'getAllDeviceArea':
             return self.getAllDeviceArea(userID, response)
+        if operation == 'getUserBrand':
+            return self.getUserBrand(userID, response)
+        if operation == 'getAreaDeviceType':
+            return self.getAreaDeviceType(userID, response)
+        if operation == 'getDeviceType':
+            return self.getDeviceType(userID, response)
+        if operation == 'getAppFrequency':
+            return self.getAppFrequency(userID, request_dict, response)
+        if operation == 'getHistoryAppFrequency':
+            return self.getAllAppFrequency(userID, response)
 
     def resetUserPwd(self, request_dict, userID, response):
         own_permission = ModelService.check_perm(userID=userID, permID=50)
@@ -213,6 +227,204 @@ class AdminManage(TemplateView):
             res = {'count': uid_list.count(), 'uid_list': list(uid_list)}
         return response.json(0, res)
 
+    def getUserBrand(self, userID, response):
+        own_permission = ModelService.check_perm(userID=userID, permID=30)
+        if own_permission is not True:
+            return response.json(404)
+        # 手机型号统计
+        print('手机型号统计:')
+        ub_qs = User_Brand.objects.values('deviceSupplier', 'deviceModel').annotate(value=Count('id')).order_by()
+        res = {
+            'value': 0,
+            'data': []
+        }
+        data = res['data']
+        tmpDict = {}
+        for ub in ub_qs:
+            deviceSupplier = ub['deviceSupplier']
+            if not tmpDict.__contains__(deviceSupplier):
+                tmpDict[deviceSupplier] = {
+                    'name': deviceSupplier,
+                    'value': 0,
+                    'children': []
+                }
+
+            item = tmpDict[deviceSupplier]
+            item['value'] = item['value'] + ub['value']
+            res['value'] = res['value'] + item['value']
+            model = {
+                'name': ub['deviceModel'],
+                'value': ub['value']
+            }
+            item['children'].append(model)
+
+        for k, v in tmpDict.items():
+            data.append(v)
+
+        print(res)
+        return response.json(0, res)
+
+    def getAreaDeviceType(self, userID, response):
+        own_permission = ModelService.check_perm(userID=userID, permID=30)
+        if own_permission is not True:
+            return response.json(404)
+        print('区域设备类型统计:')
+        di_qs = Device_Info.objects.values('area', 'Type').annotate(value=Count('UID', distinct=True)).order_by()
+        res = {
+            'quantity': 0,
+            'data': []
+        }
+        data = res['data']
+        tmpDict = {}
+        tmpDict['null'] = {
+            'area': '未知',
+            'quantity': 0,
+            'models': []
+        }
+        for di in di_qs:
+            area = di['area']
+            if area is None or area == '':
+                area = 'null'
+
+            if not tmpDict.__contains__(area):
+                tmpDict[area] = {
+                    'area': area,
+                    'quantity': 0,
+                    'models': []
+                }
+
+            item = tmpDict[area]
+            item['quantity'] = item['quantity'] + di['value']
+            res['quantity'] = res['quantity'] + item['quantity']
+            model = {
+                'model': DEVICE_TYPE[di['Type']],
+                'quantity': di['value']
+            }
+            item['models'].append(model)
+
+        for k, v in tmpDict.items():
+            data.append(v)
+        return response.json(0, res)
+
+    def getDeviceType(self, userID, response):
+        own_permission = ModelService.check_perm(userID=userID, permID=30)
+        if own_permission is not True:
+            return response.json(404)
+        # 设备类型统计
+        di_qs = Device_Info.objects.values('Type').annotate(quantity=Count('UID', distinct=True)).order_by()
+
+        # 设备型号统计
+        us_qs = UidSetModel.objects.values('deviceModel').annotate(quantity=Count('id')).order_by()
+
+        res = {
+            'type_data': {
+                'quantity': 0,
+                'data': []
+            },
+            'model_data': {
+                'quantity': 0,
+                'data': []
+            }
+        }
+        type_data = res['type_data']
+        data = type_data['data']
+        quantity = 0
+        for di in di_qs:
+            di['Type'] = DEVICE_TYPE[di['Type']]
+            quantity += di['quantity']
+            data.append(di)
+        type_data['quantity'] = quantity
+
+        model_data = res['model_data']
+        data = model_data['data']
+        quantity = 0
+        for us in us_qs:
+            data.append(us)
+            quantity += us['quantity']
+        model_data['quantity'] = quantity
+        return response.json(0, res)
+
+    def getAppFrequency(self, userID, request_dict, response):
+        own_permission = ModelService.check_perm(userID=userID, permID=30)
+        if own_permission is not True:
+            return response.json(404)
+
+        # 当前的年份
+        current_time = int(time.time())
+        localtime = time.localtime(current_time)
+        current_year = localtime.tm_year
+        current_month = localtime.tm_mon
+
+        start_year = end_year = current_year
+        end_month = current_month
+        start_month = 1
+
+        result = []
+        if end_month != 12:
+            start_month = end_month + 1
+            start_year = current_year - 1
+
+        time_struct = [start_year, start_month, 0, 0, 0, 0, 0, 0, 0]
+        key_formal = '{year}{month}'
+        for i in range(12):
+            result.append({
+                'date_time': key_formal.format(year=time_struct[0], month=str(time_struct[1]).zfill(2)),
+                'data': None
+            })
+
+            month = time_struct[1] + 1
+            if month > 12:
+                time_struct[0] = time_struct[0] + 1
+                time_struct[1] = 1
+            else:
+                time_struct[1] = month
+        #
+        afs_qs = {}
+        if start_year == end_year:
+            afs_qs = list(AppFrequencyStatisticsModel.objects.filter(year=start_year, month__gte=start_month, month__lte=end_month).values().order_by('-year', 'month'))
+        else:
+            afs_qs = list(AppFrequencyStatisticsModel.objects.filter(year=start_year, month__gte=start_month).values().order_by('-year', 'month'))
+            tmps_qs = list(AppFrequencyStatisticsModel.objects.filter(year=end_year, month__lte=end_month).values().order_by('-year', 'month'))
+            for tmp in tmps_qs:
+                afs_qs.append(tmp)
+
+        tmp_dict = {}
+
+        for afs in afs_qs:
+            key = key_formal.format(year=afs['year'], month=str(afs['month']).zfill(2))
+            tmp_dict[key] = json.loads(afs['data'])
+
+        for res in result:
+            if tmp_dict.__contains__(res['date_time']):
+                res['data'] = tmp_dict[res['date_time']]
+        print(result)
+
+        return response.json(0, result)
+
+    def getAllAppFrequency(self, userID, response):
+        own_permission = ModelService.check_perm(userID=userID, permID=30)
+        if own_permission is not True:
+            return response.json(404)
+
+        # 取出请求年份的统计好的数据
+        print('start')
+        time_struct = time.localtime()
+        current_year = time_struct.tm_year
+        start_year = current_year - 5 + 1
+        afs_qs = AppFrequencyYearStatisticsModel.objects.filter(year__gte=start_year, year__lt=current_year).order_by(
+            '-year')
+        if afs_qs.exists():
+            afs_qs = afs_qs.values('id', 'data', 'num', 'year')
+            res = []
+            for afs in afs_qs:
+                res.append({
+                    'year': afs['year'],
+                    'data': json.loads(afs['data'])
+                })
+            return response.json(0, res)
+        else:
+            return response.json(0, [])
+
 
 @require_http_methods(["GET"])
 def getUserIds(request):
@@ -299,3 +511,4 @@ def search_user_by_content(request):
         sqlDict['count'] = count
         return response.json(0, sqlDict)
     return response.json(0, {'datas': [], 'count': 0})
+

+ 2 - 0
Controller/DeviceShare.py

@@ -167,6 +167,8 @@ class DeviceShareView(View):
                     sharerDvqs.primaryMaster = primaryMaster
                     sharerDvqs.data_joined = None
                     sharerDvqs.save()
+                    redisObj = RedisObject(db=8)
+                    redisObj.del_data(key='uid_qs_' + userID)
                 except Exception as e:
                     return response.json(10, repr(e))
                 else:

+ 6 - 4
Controller/EquipmentManager.py

@@ -15,6 +15,7 @@ from Object.ETkObject import ETkObject
 import oss2
 from django.http import JsonResponse
 from Object.RedisObject import RedisObject
+import logging
 
 
 #     查询用户设备
@@ -371,6 +372,8 @@ def addInterface(request):
                             'nickname': NickName,
                         }
                         UidSetModel.objects.create(**uid_set_create_dict)
+                    else:
+                        us_qs.update(nickname=NickName)
                     pk = CommonService.getUserID(getUser=False)
                     userDevice = Device_Info(id=pk, userID_id=userID, UID=UID,
                                              NickName=NickName, View_Account=View_Account,
@@ -957,10 +960,9 @@ def update_device_shadow(request):
         request_dict = request.GET
     else:
         return response.json(444)
-    # etk = request_dict.get('etk', None)
-    # eto = ETkObject(etk)
-    # uid = eto.uid
-    uid = request_dict.get('uid', None)
+    etk = request_dict.get('etk', None)
+    eto = ETkObject(etk)
+    uid = eto.uid
     if uid:
         # 重置按钮
         is_reset = request_dict.get('is_reset', None)

+ 2 - 0
Controller/EquipmentManagerV2.py

@@ -86,6 +86,8 @@ class EquipmentManagerV2(View):
                                 'nickname': NickName,
                             }
                             UidSetModel.objects.create(**uid_set_create_dict)
+                        else:
+                            us_qs.update(nickname=NickName)
                         pk = CommonService.getUserID(getUser=False)
                         userDevice = Device_Info(id=pk, userID_id=userID, UID=UID,
                                                  NickName=NickName, View_Account=View_Account,

+ 6 - 4
Controller/EquipmentManagerV3.py

@@ -89,6 +89,8 @@ class EquipmentManagerV3(View):
                                 'nickname': NickName,
                             }
                             UidSetModel.objects.create(**uid_set_create_dict)
+                        else:
+                            us_qs.update(nickname=NickName)
                         pk = CommonService.getUserID(getUser=False)
                         userDevice = Device_Info(id=pk, userID_id=userID, UID=UID,
                                                  NickName=NickName, View_Account=View_Account,
@@ -165,8 +167,8 @@ class EquipmentManagerV3(View):
                     }
                     UidSetModel.objects.create(**uid_set_create_dict)
                 Device_Info.objects.filter(UID=uid).update(NickName=nickname)
-                redisObj = RedisObject(db=8)
-                redisObj.del_data(key='uid_qs_' + userID)
+            redisObj = RedisObject(db=8)
+            redisObj.del_data(key='uid_qs_' + userID)
             return response.json(0, res)
 
     # 新查询设备字段
@@ -302,7 +304,7 @@ class EquipmentManagerV3(View):
                         p['ucode'] = ''
                     data.append(p)
                 # 缓存时间为一个钟
-                redisObj.set_data(key='uid_qs_'+userID, val=data, expire=3600)
+                redisObj.set_data(key='uid_qs_'+userID, val=json.dumps(data), expire=3600)
                 result = data
                 print('分页')
                 # items=[]
@@ -324,7 +326,7 @@ class EquipmentManagerV3(View):
                     redis_value = json.loads(redis_value)
                 except Exception as e:
                     print(repr(e))
-                    return response.json(0, {'data': redis_value})
+                    return response.json(0, redis_value)
                 result = redis_value
 
             if NickName:

+ 137 - 0
Controller/StatisticsController.py

@@ -0,0 +1,137 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+import json
+import time
+
+from django.db.models import Count
+from django.views.decorators.csrf import csrf_exempt
+
+from Model.models import UserAppFrequencyModel, AppFrequencyStatisticsModel, Device_User, \
+    AppFrequencyYearStatisticsModel
+from Object.ResponseObject import ResponseObject
+from Object.TokenObject import TokenObject
+
+
+@csrf_exempt
+def statistcsAppFrequency(request):
+    request.encoding = 'utf-8'
+    response = ResponseObject()
+    if request.method == 'POST':
+        request_dict = request.POST
+    elif request.method == 'GET':
+        request_dict = request.GET
+    else:
+        return response.json(444)
+
+    token = TokenObject(request_dict.get('token', None))
+    if token.code != 0:
+        return response.json(token.code)
+
+    target_year = request_dict.get('year', None)
+    target_month = request_dict.get('month', None)
+
+    localtime = time.localtime()
+    current_month = localtime.tm_mon
+    current_year = localtime.tm_year
+
+    if target_year and target_month:
+        current_year = int(target_year)
+        current_month = int(target_month)
+
+    time_struct = [current_year, 1, 1, 0, 0, 0, 0, 0, 0]
+
+    # 该月的开始时间
+    time_struct[1] = current_month
+    start_time = time.mktime(tuple(time_struct))
+
+    # 该月的结束时间
+    time_struct[1] = current_month + 1
+    end_time = time.mktime(tuple(time_struct))
+
+    # 统计该月的数据
+    uaf_qs = UserAppFrequencyModel.objects.filter(data_time__gte=start_time, data_time__lt=end_time) \
+        .values('type').annotate(quantity=Count('id')).order_by()
+
+    afs_qs = AppFrequencyStatisticsModel.objects.filter(year=current_year, month=current_month)
+
+    if afs_qs.exists():
+        afs_qs.update(data=json.dumps(uaf_qs))
+    else:
+        data = {
+            'data': json.dumps(list(uaf_qs)),
+            'month': current_month,
+            'year': current_year
+        }
+        AppFrequencyStatisticsModel.objects.create(**data)
+    return response.json(0)
+
+
+@csrf_exempt
+def statistcsAppFrequencyYear(request):
+    request.encoding = 'utf-8'
+    response = ResponseObject()
+    if request.method == 'POST':
+        request_dict = request.POST
+    elif request.method == 'GET':
+        request_dict = request.GET
+    else:
+        return response.json(444)
+
+    token = TokenObject(request_dict.get('token', None))
+    if token.code != 0:
+        return response.json(token.code)
+
+    year = request_dict.get('year', None)
+
+    localtime = time.localtime()
+
+    current_year = localtime.tm_year
+    if year:
+        current_year = int(year)
+
+    afs_qs = AppFrequencyStatisticsModel.objects.filter(year=current_year).values('data', 'month')
+    # num = Device_User.objects.count()
+    num = 300000
+
+    res = []
+    result = {
+        0: 0,
+        1: 0,
+        2: 0,
+        3: 0,
+        4: 0,
+        5: 0,
+        6: 0
+    }
+    quantity = 0
+    for afs in afs_qs:
+        data = json.loads(afs['data'])
+        for item in data:
+            result[item['type']] += item['quantity']
+            quantity += item['quantity']
+
+    tmps = []
+    for k, v in result.items():
+        tmp = {
+            'type': k,
+            'value': round(v / 12 / num, 3)
+        }
+        tmps.append(tmp)
+    res.append({
+        'year': current_year,
+        'data': tmps
+    })
+    print(res)
+
+    afys_qs = AppFrequencyYearStatisticsModel.objects.filter(year=current_year)
+    #
+    if afys_qs.exists():
+        afys_qs.update(data=json.dumps(res))
+    else:
+        data = {
+            'data': json.dumps(res),
+            'year': current_year,
+            'num': num
+        }
+        AppFrequencyYearStatisticsModel.objects.create(**data)
+    return response.json(0)

+ 79 - 13
Controller/UidSetController.py

@@ -13,6 +13,9 @@
 """
 import time
 import traceback
+
+from django.db.models import Count
+
 from Object.RedisObject import RedisObject
 import simplejson as json
 from django.utils.decorators import method_decorator
@@ -20,7 +23,7 @@ from django.views.decorators.csrf import csrf_exempt
 from django.views.generic.base import View
 
 from Model.models import UidSetModel, Device_User, Device_Info, UidPushModel, Equipment_Info, UID_Preview, UID_Bucket, \
-    VodHlsModel, Order_Model, OssCrdModel, UidUserModel, UidChannelSetModel
+    VodHlsModel, Order_Model, OssCrdModel, UidUserModel, UidChannelSetModel, User_Brand
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
 from Service.CommonService import CommonService
@@ -81,9 +84,11 @@ class UidSetView(View):
         elif operation == 'update':
             return self.do_update(request_dict, response)
         elif operation == 'updateSet':
-            return self.do_update_set(request_dict, response)
+            return self.do_update_set(request, request_dict, response)
         elif operation == 'updateChannel':
             return self.do_update_channel_set(request_dict, response)
+        # elif operation == 'test':
+        #     return self.do_test(response)
         else:
             return response.json(444, 'error path')
 
@@ -194,16 +199,16 @@ class UidSetView(View):
                     else:
                         val = val + 1
                         print('UidUserModel表没有数据')
-                #有后台管理 设备配置表UidSetModel ---uid --本身,
-                #有后台管理 设备关联用户推送表Equipment_Info --devUid --独立没有儿子的,
-                #有后台管理             设备预览图表UID_Preview ---uid---孤立,
-                #有后台管理 设备关联套餐表UID_Bucket ---uid---孤立,
-                #有后台管理            云存回放信息表VodHlsModel ---uid---孤立,
-                #有后台管理 订单信息表Order_Model --UID----独立没有儿子的,
-                #有后台管理 用户设备信息表(最多信息量的表)Device_Info ---UID---孤立,
+                # 有后台管理 设备配置表UidSetModel ---uid --本身,
+                # 有后台管理 设备关联用户推送表Equipment_Info --devUid --独立没有儿子的,
+                # 有后台管理             设备预览图表UID_Preview ---uid---孤立,
+                # 有后台管理 设备关联套餐表UID_Bucket ---uid---孤立,
+                # 有后台管理            云存回放信息表VodHlsModel ---uid---孤立,
+                # 有后台管理 订单信息表Order_Model --UID----独立没有儿子的,
+                # 有后台管理 用户设备信息表(最多信息量的表)Device_Info ---UID---孤立,
                 #           设备证书OssCrdModel ---uid---孤立
                 # 有后台管理 设备ap表 UidUserModel
-                #设备绑定UidPushModel---关联表---设备配置表UidSetModel---配置表的详情有显示
+                # 设备绑定UidPushModel---关联表---设备配置表UidSetModel---配置表的详情有显示
 
                 # raise DatabaseError     #测试用,检测是否能捕捉错误
                 if val == 9:
@@ -317,11 +322,11 @@ class UidSetView(View):
             errorInfo = traceback.format_exc()
             return response.json(500, {'details': errorInfo})
 
-    def do_update_set(self, request_dict, response):
+    def do_update_set(self, request, request_dict, response):
         uid = request_dict.get('uid', None)
         deviceContent = request_dict.get('content', None)
         token = request_dict.get('token', None)
-        print(deviceContent)
+        # print(deviceContent)
         if not deviceContent or not uid:
             return response.json(444, 'content,uid')
         tko = TokenObject(token)
@@ -336,7 +341,28 @@ class UidSetView(View):
             redisObj.del_data(key='uid_qs_' + userID)
             deviceData = json.loads(deviceContent)
             uid_set_qs = UidSetModel.objects.filter(uid=uid)
-            uid_set_qs.update(**deviceData)
+            if not uid_set_qs.exists():
+                # 由于uid_set表和device_info表设备数量不一致,所以添加以下逻辑把device_info表中的相关信息保存到uid_set表
+                di_qs = Device_Info.objects.filter(UID=uid, userID=userID)
+                if di_qs.exists():
+                    di = di_qs[0]
+                    nowTime = int(time.time())
+                    uid_set_create_dict = {
+                        'uid': di.UID,
+                        'addTime': nowTime,
+                        'updTime': nowTime,
+                        'ip': CommonService.get_ip_address(request),
+                        'channel': di.ChannelIndex,
+                        'nickname': di.NickName,
+                    }
+                    for k, v in deviceData.items():
+                        uid_set_create_dict[k] = v
+                    UidSetModel.objects.create(**uid_set_create_dict)
+                else:
+                    return response.json(177)
+            else:
+                uid_set_qs.update(**deviceData)
+            print('update success')
         except Exception as e:
             return response.json(177, repr(e))
         else:
@@ -383,3 +409,43 @@ class UidSetView(View):
             return response.json(177, repr(e))
         else:
             return response.json(0)
+
+    # def do_test(self, response):
+    #     di_qs = Device_Info.objects.values('Type').annotate(c=Count('UID', distinct=True)).order_by()
+    #     for di in di_qs:
+    #         print(di)
+    #
+    #     # 设备总数量
+    #     count = Device_Info.objects.values('UID').distinct().count()
+    #     print('设备总数量:' + str(count))
+    #
+    #     # 设备型号统计
+    #     print('设备型号统计:')
+    #     us_qs = UidSetModel.objects.values('deviceModel').annotate(c=Count('id')).order_by()
+    #     for us in us_qs:
+    #         print(us)
+    #
+    #     # 手机品牌类型统计
+    #     print('手机品牌类型统计:')
+    #     ub_qs = User_Brand.objects.values('deviceSupplier').annotate(c=Count('id')).order_by()
+    #     for ub in ub_qs:
+    #         print(ub)
+    #
+    #     # 手机型号统计
+    #     print('手机型号统计:')
+    #     ub_qs = User_Brand.objects.values('deviceSupplier', 'deviceModel').annotate(c=Count('id')).order_by()
+    #     for ub in ub_qs:
+    #         print(ub)
+    #
+    #     # 区域统计
+    #     print('区域统计:')
+    #     di_qs = Device_Info.objects.values('area').annotate(c=Count('UID', distinct=True)).order_by()
+    #     for di in di_qs:
+    #         print(di)
+    #
+    #     # 区域设备类型统计
+    #     print('区域设备类型统计:')
+    #     di_qs = Device_Info.objects.values('area', 'Type').annotate(c=Count('UID', distinct=True)).order_by()
+    #     for di in di_qs:
+    #         print(di)
+    #     return response.json(0)

+ 88 - 0
Controller/UserBrandControllerV2.py

@@ -0,0 +1,88 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+from django.utils.decorators import method_decorator
+from django.views.decorators.csrf import csrf_exempt
+from django.views.generic.base import View
+
+from Model.models import User_Brand, Device_User
+from Object.ResponseObject import ResponseObject
+from Object.TokenObject import TokenObject
+
+
+class UserBrandV2(View):
+    @method_decorator(csrf_exempt)
+    def dispatch(self, *args, **kwargs):
+        return super(UserBrandV2, self).dispatch(*args, **kwargs)
+
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        operation = kwargs.get('operation')
+        request_dict = request.GET
+        return self.validate(request_dict, operation)
+
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        operation = kwargs.get('operation')
+        request_dict = request.POST
+        return self.validate(request_dict, operation)
+
+    def validate(self, request_dict, operation):
+        token = request_dict.get('token', None)
+
+        response = ResponseObject()
+        token = TokenObject(token)
+
+        if token.code != 0:
+            return response.json(token.code)
+
+        if operation == 'add':
+            return self.do_add(token.userID, request_dict, response)
+        elif operation == 'query':
+            return self.do_query(token.userID, request_dict, response)
+        else:
+            return response.json(404)
+
+    def do_add(self, userID, request_dict, response):
+        deviceSupplier = request_dict.get('deviceSupplier', None)
+        deviceModel = request_dict.get('deviceModel', None)
+        osType = request_dict.get('osType', None)
+        osVersion = request_dict.get('osVersion', None)
+
+        if userID and deviceSupplier and deviceModel and osType and osVersion:
+            ub_qs = User_Brand.objects.filter(userID=userID)
+            if ub_qs.exists():
+                update = {
+                    'deviceSupplier': deviceSupplier,
+                    'deviceModel': deviceModel,
+                    'osType': osType,
+                    'osVersion': osVersion
+                }
+                ub_qs.update(**update)
+                return response.json(0)
+            else:
+                user = Device_User.objects.filter(userID=userID)
+                if not user.exists():
+                    return response.json(104)
+                data = {
+                    'userID': user[0],
+                    'deviceSupplier': deviceSupplier,
+                    'deviceModel': deviceModel,
+                    'osType': osType,
+                    'osVersion': osVersion
+                }
+                User_Brand.objects.create(**data)
+                return response.json(0)
+        else:
+            return response.json(444)
+
+    def do_query(self, userID, request_dict, response):
+
+        if not userID:
+            return response.json(444)
+        else:
+            ub_qs = User_Brand.objects.filter(userID=userID)
+            data = None
+            if ub_qs.exists():
+                data = ub_qs.values('id', 'deviceSupplier', 'deviceModel', 'osType', 'osVersion')[0]
+
+            return response.json(0, {'data': data})

+ 263 - 33
Controller/UserController.py

@@ -27,7 +27,8 @@ from ratelimit.decorators import ratelimit
 
 from Ansjer.config import AuthCode_Expire, SERVER_DOMAIN, APNS_CONFIG, JPUSH_CONFIG, FCM_CONFIG, TUTK_PUSH_DOMAIN
 from Controller.CheckUserData import DataValid, date_handler, RandomStr
-from Model.models import Device_User, Role, UidPushModel, UserOauth2Model, UserExModel, Device_Info,UidSetModel
+from Model.models import Device_User, Role, UidPushModel, UserOauth2Model, UserExModel, Device_Info, UidSetModel, \
+    UserAppFrequencyModel
 from Object.AWS.SesClassObject import SesClassObject
 from Object.AliSmsObject import AliSmsObject
 from Object.RedisObject import RedisObject
@@ -50,7 +51,7 @@ class authCodeView(TemplateView):
 
     @method_decorator(csrf_exempt)
     def dispatch(self, *args, **kwargs):
-		# testtest11111111111111
+        # testtest11111111111111
         return super(authCodeView, self).dispatch(*args, **kwargs)
 
     @ratelimit(key='ip', rate='2/m')
@@ -440,7 +441,6 @@ class v3ChangePwdView(TemplateView):
             return response.json(177)
 
 
-
 class ForgetPwdView(TemplateView):
     '''
     忘记密码
@@ -972,7 +972,6 @@ class v2registerView(TemplateView):
             return self.do_login(email_qs, response)
 
 
-
 # 验证码注册v3
 class v3registerView(TemplateView):
     @method_decorator(csrf_exempt)
@@ -1148,7 +1147,6 @@ class v3registerView(TemplateView):
             return self.do_login(email_qs, response)
 
 
-
 # 重置密码
 # 忘记密码获取验证码v2
 class v2forgetPwdCodeView(TemplateView):
@@ -1414,7 +1412,6 @@ class v2resetPwdByCodeView(TemplateView):
         return response.json(0, res)
 
 
-
 # 忘记密码v3
 class v3resetPwdByCodeView(TemplateView):
     @method_decorator(csrf_exempt)
@@ -1572,7 +1569,6 @@ class v3resetPwdByCodeView(TemplateView):
         return response.json(0, res)
 
 
-
 # 登录
 class v2LoginView(TemplateView):
     @method_decorator(csrf_exempt)  # @csrf_exempt
@@ -1672,7 +1668,7 @@ class v2LoginView(TemplateView):
 class v3LoginView(TemplateView):
     @method_decorator(csrf_exempt)  # @csrf_exempt
     def dispatch(self, *args, **kwargs):
-        #chong 
+        # chong
         return super(v3LoginView, self).dispatch(*args, **kwargs)
 
     @ratelimit(key='ip', rate='5/m')
@@ -1714,13 +1710,13 @@ class v3LoginView(TemplateView):
                     password = password.decode('utf-8')
                     # 截去第一位,最后一位
                     password = password[1:-1]
-                if i==2:
+                if i == 2:
                     # 第2次先解密
                     password = base64.b64decode(password)
                     password = password.decode('utf-8')
                     # 去前2位,后2位
                     password = password[2:-2]
-                if i==3:
+                if i == 3:
                     # 第3次先解密
                     password = base64.b64decode(password)
                     password = password.decode('utf-8')
@@ -1819,7 +1815,7 @@ class InitInfoView(View):
         tz = request_dict.get('tz', '0')
         lang = request_dict.get('lang', '')  # 语言区域
         now_time = int(time.time())
-        if all([token_val, push_type, appBundleId,userID]):
+        if all([token_val, push_type, appBundleId, userID]):
             push_type = int(push_type)
             if push_type == 0:
                 if appBundleId not in APNS_CONFIG.keys():
@@ -2580,11 +2576,12 @@ class alexaAuthView(TemplateView):
         #     uid_arr.append({'uid': uid_q['UID'], 'nick': uid_q['NickName'], 'password': uid_q['View_Password']})
         res = {
             'userID': userID,
-        #     'uid_arr': uid_arr
+            #     'uid_arr': uid_arr
         }
-        return response.json(0,res)
+        return response.json(0, res)
         # return response.json(0, res)
 
+
 class alexaUidView(TemplateView):
     def post(self, request, *args, **kwargs):
         request.encoding = 'utf-8'
@@ -2609,11 +2606,11 @@ class alexaUidView(TemplateView):
             uid_list = []
             for uid_q in uid_qs:
                 uid_list.append(uid_q['UID'])
-                uid_arr.append({'uid': uid_q['UID'], 'nick': uid_q['NickName'], 'password': uid_q['View_Password'],})
+                uid_arr.append({'uid': uid_q['UID'], 'nick': uid_q['NickName'], 'password': uid_q['View_Password'], })
             res = {
                 'uid_arr': uid_arr
             }
-            return response.json(0,res)
+            return response.json(0, res)
         else:
             return response.json(107)
 
@@ -2626,16 +2623,16 @@ class alexaUidView(TemplateView):
             uid_dict = {}
             uid_list = []
             for uid_q in uid_qs:
-                #追加
+                # 追加
                 uid_list.append(uid_q['UID'])
-                #给uid_q['UID']赋值
+                # 给uid_q['UID']赋值
                 uid_dict[uid_q['UID']] = {'nick': uid_q['NickName'], 'password': uid_q['View_Password']}
             us_qs = UidSetModel.objects.filter(uid__in=uid_list, is_alexa=2).values('uid', 'region_alexa')
             # uid,password,region的列表
             uid_arr = []
             for us in us_qs:
                 uid = us['uid']
-                #设备alexa区域
+                # 设备alexa区域
                 region_alexa = us['region_alexa']
                 if region_alexa == '':
                     region_alexa = "en"
@@ -2650,6 +2647,7 @@ class alexaUidView(TemplateView):
         else:
             return response.json(107)
 
+
 # 登出
 class V2LogoutView(TemplateView):
     @method_decorator(csrf_exempt)
@@ -2811,14 +2809,14 @@ class Image_Code_RegisterView(TemplateView):
         request_dict = request.GET
         return self.validates(request_dict)
 
-    #检测验证码,并注册
-    def validates(self,request_dict):
+    # 检测验证码,并注册
+    def validates(self, request_dict):
         print("__________request_dict:%s" % request_dict)
-        userEmail = request_dict.get('userEmail',None)
-        password = request_dict.get('userPwd',None)
-        lang = request_dict.get('lang',None)
-        #前端传进来的uuid
-        imageCodeId = request_dict.get('imageCodeId',None)
+        userEmail = request_dict.get('userEmail', None)
+        password = request_dict.get('userPwd', None)
+        lang = request_dict.get('lang', None)
+        # 前端传进来的uuid
+        imageCodeId = request_dict.get('imageCodeId', None)
         # 页面输入的验证码
         response = ResponseObject(lang)
         valid_code = request_dict.get('id_v_code', None)
@@ -2839,7 +2837,7 @@ class Image_Code_RegisterView(TemplateView):
                     password = base64.b64decode(password)
                     password = password.decode('utf-8')
                     password = password[3:-3]
-            print("password%s"%password)
+            print("password%s" % password)
         except Exception as e:
             return response.json(111)
         try:
@@ -2856,7 +2854,7 @@ class Image_Code_RegisterView(TemplateView):
                     valid_code = base64.b64decode(valid_code)
                     valid_code = valid_code.decode('utf-8')
                     valid_code = valid_code[3:-3]
-            print("valid_code:%s"%valid_code)
+            print("valid_code:%s" % valid_code)
         except Exception as e:
             return response.json(121)
         if not userEmail:
@@ -2870,16 +2868,16 @@ class Image_Code_RegisterView(TemplateView):
             emailValid = Device_User.objects.filter(userEmail=userEmail)
             if emailValid:
                 return response.json(103)
-        #根据uuid拼接的key
-        image_code_key = "image_code_%s" %imageCodeId
-        #判断验证码是否过期
+        # 根据uuid拼接的key
+        image_code_key = "image_code_%s" % imageCodeId
+        # 判断验证码是否过期
         if image_code_key is None:
             return response.json(120)
         redisObj = RedisObject(db=6)
-        #redis里面的验证码
+        # redis里面的验证码
         redis_image_code = redisObj.get_data(key=image_code_key)
-        #验证用户输入的验证码和redis中的验证码
-        if valid_code.lower()!=redis_image_code.lower():
+        # 验证用户输入的验证码和redis中的验证码
+        if valid_code.lower() != redis_image_code.lower():
             return response.json(121)
         # 删除redis中的图片验证码,防止用户使用同一个图片验证码验证多次
         redisObj.del_data(key=image_code_key)
@@ -2930,8 +2928,240 @@ class Image_Code_RegisterView(TemplateView):
         return response.json(0, res)
 
 
+class UserAppFrequencyView(TemplateView):
+    @method_decorator(csrf_exempt)
+    def dispatch(self, *args, **kwargs):
+        return super(UserAppFrequencyView, self).dispatch(*args, **kwargs)
+
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        request_dict = request.POST
+        operation = kwargs.get('operation')
+        return self.validates(request_dict, operation)
+
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        request_dict = request.GET
+        operation = kwargs.get('operation')
+        return self.validates(request_dict, operation)
+
+    def validates(self, request_dict, operation):
+        token = request_dict.get('token', None)
+        response = ResponseObject()
+
+        token = TokenObject(token)
+        if token.code != 0:
+            return response.json(token.code)
+
+        if operation == 'refresh':
+            return self.do_refresh(request_dict, token.userID, response)
+        else:
+            return response.json(404)
+
+    def do_refresh(self, request_dict, userID, response):
+        # return response.json(0)
+        type = request_dict.get('type', None)
+        month = request_dict.get('month', None)
+        if not type or not month:
+            return response.json(444, 'type')
+        else:
+            type = int(type)
+            now_time = int(time.time())
+            month = int(month)
+            uaf_qs = UserAppFrequencyModel.objects.filter(user__userID=userID)
+
+            if not uaf_qs.exists():
+                user = Device_User.objects.filter(userID=userID)[0]
+                data = {
+                    'user': user,
+                    'type': type,
+                    'data_time': month,
+                    'add_time': now_time,
+                    'update_time': now_time,
+                }
+                UserAppFrequencyModel.objects.create(**data)
+                return response.json(0)
+            else:
+                updateMonth = time.strftime('%m', time.localtime(month))
+                uaf = uaf_qs.values('id', 'type', 'data_time')[0]
+                dbMonth = time.strftime('%m', time.localtime(int(uaf['data_time'])))
+                print('update month is ' + updateMonth)
+                print('db month is ' + dbMonth)
+                if updateMonth == dbMonth:
+                    UserAppFrequencyModel.objects.filter(id=uaf['id']).update(type=type)
+                    return response.json(0)
+                elif updateMonth > dbMonth:
+                    user = Device_User.objects.filter(userID=userID)[0]
+                    data = {
+                        'user': user,
+                        'type': type,
+                        'data_time': month,
+                        'add_time': now_time,
+                        'update_time': now_time,
+                    }
+                    UserAppFrequencyModel.objects.create(**data)
+                    return response.json(0)
+                else:
+                    return response.json(444, 'month')
+
+
+class loginCodeView(View):
+    @method_decorator(csrf_exempt)  # @csrf_exempt
+    def dispatch(self, *args, **kwargs):
+        return super(loginCodeView, self).dispatch(*args, **kwargs)
 
+    @ratelimit(key='ip', rate='2/m')
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        lang = request.POST.get('lang', None)
+        if not lang:
+            lang = request.POST.get('language', None)
+        response = ResponseObject(lang)
+        request_dict = request.POST
+        phone = request_dict.get('phone', None)
+        if phone is not None:
+            was_limited = getattr(request, 'limited', False)
+            if was_limited is True:
+                return response.json(5)
+        return self.validate(request_dict, response)
 
+    @ratelimit(key='ip', rate='2/m')
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        lang = request.GET.get('lang', None)
+        if not lang:
+            lang = request.GET.get('language', None)
+        response = ResponseObject(lang)
+        was_limited = getattr(request, 'limited', False)
+        if was_limited is True:
+            return response.json(5)
+        request_dict = request.GET
+        return self.validate(request_dict, response)
 
+    def validate(self, request_dict, response):
+        phone = request_dict.get('phone', None)
+        country_code = request_dict.get('country_code', None)
+        sign_name = request_dict.get('sign_name', None)
 
+        if phone and sign_name:
+            du_qs = Device_User.objects.filter(username=phone)
+            if not du_qs.exists():
+                return response.json(104)
+            else:
+                redisObject = RedisObject()
+                login_code_key = '{phone}_login_code'.format(phone=phone)
+                login_code = redisObject.get_data(key=login_code_key)
+                login_code_ttl = redisObject.get_ttl(key=login_code_key)
+                if login_code_ttl > 240 and login_code:
+                    return response.json(90)
+                login_code = RandomStr(6, True)
+                aliSms = AliSmsObject()
+                if sign_name == 'zosi':
+                    sign_sms = '周视'
+                else:
+                    sign_sms = 'Ansjer'
 
+                res = aliSms.send_code_sms(phone=phone, code=login_code, sign_name=sign_sms, temp_msg='SMS_151600991')
+
+                if res['Code'] == 'OK':
+                    if redisObject.set_data(key=login_code_key, val=login_code, expire=300) is not True:
+                        return response.json(48)
+                    return response.json(0)
+                else:
+                    return response.json(10, res['Message'])
+        else:
+            return response.json(444)
+
+
+class v3LoginByCodeView(View):
+    @method_decorator(csrf_exempt)  # @csrf_exempt
+    def dispatch(self, *args, **kwargs):
+        return super(v3LoginByCodeView, self).dispatch(*args, **kwargs)
+
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        lang = request.POST.get('lang', None)
+        if not lang:
+            lang = request.POST.get('language', None)
+        response = ResponseObject(lang)
+        request_dict = request.POST
+        phone = request_dict.get('phone', None)
+        if phone is not None:
+            was_limited = getattr(request, 'limited', False)
+            if was_limited is True:
+                return response.json(5)
+        return self.validate(request_dict, response)
+
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        lang = request.GET.get('lang', None)
+        if not lang:
+            lang = request.GET.get('language', None)
+        response = ResponseObject(lang)
+        was_limited = getattr(request, 'limited', False)
+        if was_limited is True:
+            return response.json(5)
+        request_dict = request.GET
+        return self.validate(request_dict, response)
+
+    def validate(self, request_dict, response):
+        phone = request_dict.get('phone', None)
+        code = request_dict.get('code', None)
+
+        if phone and code:
+            redisObject = RedisObject()
+            login_code_key = '{phone}_login_code'.format(phone=phone)
+            login_code = redisObject.get_data(key=login_code_key)
+
+            if login_code is not False:
+                print(code)
+                code = CommonService.decode_data(code)
+                print(code)
+                if login_code == code:
+                    if response.lang is None:
+                        response.lang = 'en'
+                    return self.do_phone_login(phone, response)
+                else:
+                    return response.json(121)
+            else:
+                return response.json(120)
+
+    def do_phone_login(self, phone, response):
+        user_qs = Device_User.objects.filter(Q(phone=phone) | Q(username=phone), is_active=True,
+                                             user_isValid=True)
+        return self.valid_login(user_qs, response)
+
+    def valid_login(self, user_qs, response):
+        if not user_qs.exists():
+            return response.json(104)
+        # users = user_qs.values('role__rid', 'role__roleName', 'userID', 'role', 'NickName', 'username', 'userEmail',
+        #                        'phone', 'password', 'userIconPath', 'user_isValid', 'is_active')[0]
+        users = user_qs.values('role__rid', 'role__roleName', 'userID', 'NickName', 'username', 'userEmail',
+                               'phone', 'password', 'userIconPath')[0]
+
+        userID = users['userID']
+        tko = TokenObject()
+        res = tko.generate(
+            data={'userID': userID, 'lang': response.lang, 'user': users['username'],
+                  'm_code': '123413243214'})
+        if tko.code == 0:
+            now_time = datetime.datetime.utcnow().replace(tzinfo=utc).astimezone(utc)
+            user_qs.update(last_login=now_time, language=response.lang)
+            res['rid'] = users['role__rid']
+            res['roleName'] = users['role__roleName']
+            res['permList'] = ModelService.own_permission(userID)
+            res['userID'] = userID
+            # 昵称,邮箱,电话,刷新,头像
+            userIconPath = str(users['userIconPath'])
+            if userIconPath and userIconPath.find('static/') != -1:
+                userIconPath = userIconPath.replace('static/', '').replace('\\', '/')
+                res['userIconUrl'] = SERVER_DOMAIN + 'account/getAvatar/' + userIconPath
+            else:
+                res['userIconUrl'] = ''
+            res['NickName'] = users['NickName'] if users['NickName'] is not None else ''
+            res['username'] = users['username'] if users['username'] is not None else ''
+            res['userEmail'] = users['userEmail'] if users['userEmail'] is not None else ''
+            res['phone'] = users['phone'] if users['phone'] is not None else ''
+            return response.json(0, res)
+        else:
+            return response.json(tko.code)

+ 39 - 0
Model/models.py

@@ -908,3 +908,42 @@ class GrantCodeModel(models.Model):
         ordering = ('-add_time',)
         verbose_name = u'授权码表'
         db_table = 'oauth_grant_code'
+
+
+class UserAppFrequencyModel(models.Model):
+    id = models.AutoField(primary_key=True)
+    user = models.ForeignKey(Device_User, to_field='userID', on_delete=models.CASCADE, verbose_name='关联设备用户表')
+    type = models.SmallIntegerField(default=0, verbose_name='使用频率类型') # 1:每天,2:三天,3:一周,4:两周,5:一个月,6:一个月以上
+    data_time = models.IntegerField(default=0, verbose_name='数据时间')
+    add_time = models.IntegerField(default=0, verbose_name='添加时间')
+    update_time = models.IntegerField(default=0, verbose_name='更新时间')
+
+    class Meta:
+        verbose_name = '用户使用APP频率表'
+        verbose_name_plural = verbose_name
+        db_table = 'user_app_frequency'
+        ordering = ('-add_time',)
+
+
+class AppFrequencyStatisticsModel(models.Model):
+    id = models.AutoField(primary_key=True)
+    data = models.TextField(default='', verbose_name='统计好的数据')
+    month = models.IntegerField(default=0, verbose_name='月份')
+    year = models.IntegerField(default=0, verbose_name='年份')
+
+    class Meta:
+        verbose_name = 'app月使用频率统计表'
+        verbose_name_plural = verbose_name
+        db_table = 'app_frequency_statistics'
+
+
+class AppFrequencyYearStatisticsModel(models.Model):
+    id = models.AutoField(primary_key=True)
+    data = models.TextField(default='', verbose_name='统计好的数据')
+    year = models.IntegerField(default=0, verbose_name='年份')
+    num = models.IntegerField(default=0, verbose_name='总人数')
+
+    class Meta:
+        verbose_name = 'app使用频率统计表,年度统计'
+        verbose_name_plural = verbose_name
+        db_table = 'app_frequency_year_statistics'

+ 24 - 1
Service/CommonService.py

@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+import base64
 import datetime
 import time
 from pathlib import Path
@@ -221,4 +222,26 @@ class CommonService:
         random = Random()
         for index in range(randomlength):
             str += characterSet[random.randint(0, length)]
-        return str
+        return str
+
+    @staticmethod
+    def decode_data(content):
+        try:
+            for i in range(1, 4):
+                if i == 1:
+                    content = base64.b64decode(content)
+                    content = content.decode('utf-8')
+                    content = content[1:-1]
+                if i == 2:
+                    content = base64.b64decode(content)
+                    content = content.decode('utf-8')
+                    content = content[2:-2]
+                if i == 3:
+                    content = base64.b64decode(content)
+                    content = content.decode('utf-8')
+                    content = content[3:-3]
+
+            return content
+        except Exception as e:
+            print(e)
+            return None

+ 1 - 0
Service/TemplateService.py

@@ -78,6 +78,7 @@ class TemplateService:
             'v3/account/register',
             'v3/account/changePwd',
             'v3/account/resetPwdByCode',
+            'account/appFrequency',
         ]
         return apiList