Browse Source

添加Alexa、统计、问题帮助等

tanghongbin 5 years ago
parent
commit
9ce36b0763

+ 8 - 6
Ansjer/config_local.py

@@ -15,12 +15,14 @@
 OAUTH_ACCESS_TOKEN_SECRET = 'local_a+jbgnw%@1%zy^=@dn62%'
 OAUTH_REFRESH_TOKEN_SECRET = 'local_r+jbgnw%@1%zy^=@dn62%'
 
-NGINX_RTMP_STAT = 'http://192.168.136.45:8077/stat'
-SERVER_DOMAIN = 'http://192.168.136.45:8077/'
-SERVER_DOMAIN_SSL = 'http://192.168.136.45:8077/'
-SERVER_HOST = '192.168.136.45'
-DOMAIN_HOST = '192.168.136.45'
-RTMP_PUSH_URL = 'rtmp://192.168.136.45:1935/hls'
+NGINX_RTMP_STAT = 'http://192.168.136.99:8077/stat'
+SERVER_DOMAIN = 'http://192.168.136.99:8077/'
+SERVER_DOMAIN_SSL = 'http://192.168.136.99:8077/'
+SERVER_HOST = '192.168.136.99'
+DOMAIN_HOST = '192.168.136.99'
+# SERVER_HOST = '127.0.0.1'
+# DOMAIN_HOST = '192.168.136.99'
+RTMP_PUSH_URL = 'rtmp://192.168.136.99:1935/hls'
 PAYPAL_CRD = {
     "mode": "sandbox",  # sandbox or live
     "client_id": "AeuhR7FHisO-lOd2OwtzyDu7PSLMmDZoDLgmzuEQ12WCtTu_8Z1AzcD4gG5SnymnuvJs-n5KBB8H9Z_G",

+ 17 - 4
Ansjer/urls.py

@@ -10,7 +10,7 @@ from Controller import FeedBack, EquipmentOTA, EquipmentInfo, AdminManage, AppIn
     StsOssController, UIDPreview, OssCrd, SysMsg, UidUser, EquipmentManagerV2, EquipmentManagerV3, PushDeploy, \
     AppSetController, \
     ApplicationController, UserExController, CloudStorage, TestApi, UserBrandControllerV2, \
-    StatisticsController
+    StatisticsController, Alexa, FAQController
 
 urlpatterns = [
     url(r'^testApi/(?P<operation>.*)$', TestApi.testView.as_view()),
@@ -127,6 +127,10 @@ urlpatterns = [
     url(r'^account/loginCode$', UserController.loginCodeView.as_view()),
     url(r'^v3/account/loginByCode$', UserController.v3LoginByCodeView.as_view()),
 
+    # 指纹登录
+    url(r'^v3/account/loginByFingerprint$', UserController.v3LoginByFingerprintView.as_view()),
+    url(r'^v3/account/setFingerprint$', UserController.v3SetFingerprintView.as_view()),
+
     # 新增
     url(r'^detect/detect_group_push$',DetectController.NotificationView.detect_group_push),
     url(r'^detect/add$', DetectController.PushNotificationView.as_view()),
@@ -210,10 +214,19 @@ 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'^account/appFrequency/(?P<operation>.*)$', UserController.UserAppFrequencyView.as_view()),
     url(r'^v2/userbrand/(?P<operation>.*)$', UserBrandControllerV2.UserBrandV2.as_view()),
-    # url(r'^statistcs/appFrequencyMonth$', StatisticsController.statistcsAppFrequency),
-    # url(r'^statistcs/appFrequencyYear$', StatisticsController.statistcsAppFrequencyYear),
+    url(r'^statistcs/appFrequencyMonth$', StatisticsController.statistcsAppFrequency),
+    url(r'^statistcs/appFrequencyYear$', StatisticsController.statistcsAppFrequencyYear),
+
+    #统计alexa连接数
+    url(r'^alexa/(?P<operation>.*)$', Alexa.AlexaConnectNum.as_view()),
+
+    # FAQ
+    url(r'^faq/upload', FAQController.FAQUploadView.as_view()),
+    url(r'^faq/image/(?P<filePath>.*)$', FAQController.getFAQImage.as_view()),
+    url(r'^faq/(?P<operation>.*)$', FAQController.FAQView.as_view()),
+
     # app 设备消息模板
     # 路由加参数参考
     # url(r'^(?P<path>.*)/(?P<UID>.*)/lls$', Test.Test.as_view(), name=u'gg'),

+ 86 - 85
Controller/AdminManage.py

@@ -6,7 +6,8 @@ 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, User_Brand, UidSetModel
+from Model.models import Device_Info, Role, UserExModel, User_Brand, UidSetModel, AppFrequencyYearStatisticsModel, \
+    AppFrequencyStatisticsModel
 from Service.ModelService import ModelService
 from django.utils import timezone
 from Model.models import Access_Log, Device_User
@@ -73,10 +74,10 @@ class AdminManage(TemplateView):
             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)
+        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)
@@ -343,86 +344,86 @@ class AdminManage(TemplateView):
         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, [])
+    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"])

+ 132 - 0
Controller/Alexa.py

@@ -0,0 +1,132 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""
+@Copyright (C) ansjer cop Video Technology Co.,Ltd.All rights reserved.
+@AUTHOR: ASJRD018
+@NAME: Ansjer
+@software: PyCharm
+@DATE: 2020/8/14 10:13
+@Version: python3.6
+@MODIFY DECORD:ansjer dev
+@file: AlexaConnectNum.py
+@Contact: sonalh@foxmail.com
+"""
+from django.views.generic.base import View
+import os
+
+import json
+import math
+import time
+import urllib
+import logging
+import logging
+import requests
+import time
+import datetime
+from django.http import JsonResponse, HttpResponseRedirect, HttpResponse
+from Model.models import AlexaConnectStatisticsModel
+from django.views.generic import TemplateView
+from django.utils.decorators import method_decorator
+from django.views.decorators.csrf import csrf_exempt
+from django.views.generic.base import View
+from django.contrib.auth.hashers import make_password, check_password  # 对密码加密模块
+from Object.ResponseObject import ResponseObject
+from Object.TokenObject import TokenObject
+from Service.ModelService import ModelService
+from django.db import connection
+
+rtspServer = "rtsp.zositech.org,3.16.66.144"
+
+# 获取alexa连接数接口
+class AlexaConnectNum(TemplateView):
+    @method_decorator(csrf_exempt)
+    def dispatch(self, *args, **kwargs):
+        return super(AlexaConnectNum, self).dispatch(*args, **kwargs)
+
+    def get(self, request, *args, **kwargs):
+        response = ResponseObject()
+        request.encoding = 'utf-8'
+        operation = kwargs.get('operation')
+        #每隔十分钟定时保存每天最高连接数,crontab 在alexa_oauth2_oserver
+        if operation == 'saveConnectNum':
+            today = datetime.date.today()
+            today_start_time = int(time.mktime(time.strptime(str(today), '%Y-%m-%d')))
+            today_end_time = int(time.mktime(time.strptime(str(today), '%Y-%m-%d'))) + 86399
+             #获取当前连接数
+            current_connect_num = self.currentConnect()
+            today_data = AlexaConnectStatisticsModel.objects.\
+                filter(data_time__lte=today_end_time,data_time__gte=today_start_time).values('num','data_time')
+            if today_data.exists():
+                num = list(today_data)[0]['num']
+                if current_connect_num > num:
+                    today_data.update(num=current_connect_num, data_time=time.time())
+            else:
+                today_data.create(num=current_connect_num, data_time=time.time())
+            return response.json(0)
+        return response.json(10006)
+
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        response = ResponseObject()
+        operation = kwargs.get('operation')
+        post_data = request.POST
+        token = post_data.get('token', None)
+        # tko = TokenObject()
+        # newToken = tko.generate( data={'userID': '158943594633713800138000', 'lang': 'cn', 'user': '597471180@qq.com', 'm_code': '123413243214'})
+        # return response.json(0, {'data': newToken})
+        tko = TokenObject(token)
+        response.lang = tko.lang
+        if tko.code != 0:
+            return response.json(tko.code)
+        userID = tko.userID
+        own_permission = ModelService.check_perm(userID=userID, permID=30)
+        if own_permission is not True:
+            return response.json(404)
+
+        #获取当前连接数
+        current_connect_num = self.currentConnect()
+        res = []
+        #最近三十天每天最高连接数
+        if operation == 'thirtyDays':
+            query_num = AlexaConnectStatisticsModel.objects.\
+                extra(select={"data_time": "FROM_UNIXTIME(data_time, '%%m-%%d')"}).\
+                values('num', 'data_time').order_by('-data_time')[:30]
+            res = list(query_num)
+
+        #最近十二个月每月最高连接数
+        if operation == 'years':
+            cursor=connection.cursor()
+            cursor.execute("SELECT FROM_UNIXTIME(data_time,'%Y-%m') as month, max(num) as max_num FROM alexa_statistics GROUP BY month order by month asc LIMIT 12")
+            res_query = cursor.fetchall()
+            for max_num, month in res_query:
+                res.append({'num':month, 'month':max_num})
+
+        res_desc = {'result_code': 0, 'reason': '成功', 'current_num':current_connect_num, 'top_num': res, 'error_code': 0}
+        result_json = json.dumps(res_desc, ensure_ascii=False)
+        return HttpResponse(result_json)
+
+    def currentConnect(self):
+        urls = rtspServer.split(',')
+        httpPrefix = 'http://'
+        postfix = ':10008/api/v1/pushers'
+        current_connect_num = 0
+        for url in urls:
+            apiUrl = httpPrefix + url + postfix
+            try:
+                selectRtsp = requests.get(url=apiUrl, timeout=5)
+                current_connect_num += selectRtsp.json()['total']
+            except Exception as e:
+                continue
+        return current_connect_num
+
+
+
+
+
+
+
+
+
+
+
+

+ 3 - 3
Controller/EquipmentManagerV3.py

@@ -136,13 +136,15 @@ class EquipmentManagerV3(View):
         if userID is None:
             return response.json(309)
         try:
-            deviceData = json.loads(deviceContent)
+            # deviceData = json.loads(deviceContent)
+            deviceData = eval(deviceContent)
             # print(deviceData['View_Password'])
             if deviceData.__contains__('View_Password'):
                 deviceData['View_Password'] = self.decode_pwd(deviceData['View_Password'])
             dev_info_qs = Device_Info.objects.filter(userID_id=userID, id=id)
             dev_info_qs.update(**deviceData)
         except Exception as e:
+            print(e)
             return response.json(177, repr(e))
         else:
             qs = Device_Info.objects.filter(userID_id=userID, id=id)
@@ -316,8 +318,6 @@ class EquipmentManagerV3(View):
                 # return response.json(0, items)
             else:
                 # print('去缓存找数据')
-                print('redis_value: ')
-                print(redis_value)
                 # redis_value = redis_value.replace("'", '"')
                 redis_value = redis_value.replace('"isShare": True', '"isShare": true')
                 redis_value = redis_value.replace('"isShare": False', '"isShare": false')

+ 318 - 0
Controller/FAQController.py

@@ -0,0 +1,318 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+import json
+import os
+import shutil
+import time
+import traceback
+
+from django.http import HttpResponse
+from django.utils.decorators import method_decorator
+from django.views.decorators.csrf import csrf_exempt
+from django.views.generic.base import View
+
+from Ansjer.config import BASE_DIR, SERVER_TYPE
+from Ansjer.config_formal import SERVER_DOMAIN
+from Ansjer.config_test import SERVER_DOMAIN
+from Model.models import FAQModel
+from Object.RedisObject import RedisObject
+from Object.ResponseObject import ResponseObject
+from Object.TokenObject import TokenObject
+from var_dump import var_dump
+
+from Service.ModelService import ModelService
+
+
+class FAQUploadView(View):
+    @method_decorator(csrf_exempt)
+    def dispatch(self, request, *args, **kwargs):
+        return super(FAQUploadView, self).dispatch(request, *args, **kwargs)
+
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        request_dict = request.GET
+        fileName = request.FILES.get('fileName', None)
+        return self.validate(fileName, request_dict)
+
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        request_dict = request.POST
+        fileName = request.FILES.get('fileName', None)
+        return self.validate(fileName, request_dict)
+
+    def validate(self, fileName, request_dict):
+
+        token = TokenObject(request_dict.get('token', None))
+
+        response = ResponseObject()
+        if token.code != 0:
+            return response.json(token.code)
+
+        own_permission = ModelService.check_perm(userID=token.userID, permID=120)
+        if own_permission is not True:
+            return response.json(404)
+
+        try:
+            redisObject = RedisObject()
+            path = '/'.join((BASE_DIR, 'static/FAQImages/tmp')).replace('\\', '/') + '/'
+            # path = '/'.join((BASE_DIR, 'static/{user}/FAQImages'.format(user=token.userID))).replace('\\', '/') + '/'
+            if not os.path.exists(path):
+                os.makedirs(path)
+
+            # 先从redis中取出token对应的图片信息
+            images = redisObject.get_data(key=token.token)
+            if images is not False:
+                images = json.loads(images)
+                # 判断此次编辑是否已经存在对应的图片
+                if images.__contains__(str(fileName)):
+                    file_name = images[str(fileName)]
+                    index = file_name.find('static/')
+                    filePath = file_name[index:]
+                    filePath = SERVER_DOMAIN + 'faq/image/' + filePath
+                    # filePath = "http://192.168.136.35:8000/" + 'faq/image/' + filePath
+                    return response.json(0, {'filePath': filePath})
+
+            # redis中没有对应的图片信息
+            tmp_name = str(fileName)
+            suffix = tmp_name[tmp_name.find('.'):]
+            tmp_file_name = int(time.time())
+            tmp_file_name = '{file_name}{suffix}'.format(file_name=tmp_file_name, suffix=suffix)
+
+            file_name = path + str(tmp_file_name)
+            if os.path.exists(file_name):
+                os.remove(file_name)
+
+            destination = open(file_name, 'wb+')
+            for chunk in fileName.chunks():
+                destination.write(chunk)
+            destination.close()
+
+            # 把图片信息保存到redis中
+            images = redisObject.get_data(token.token)
+            if images is False:
+                images = json.dumps({})
+
+            images = json.loads(images)
+            images[tmp_name] = file_name
+            redisObject.set_data(key=token.token, val=json.dumps(images), expire=3600)
+
+        except Exception as e:
+            errorInfo = traceback.format_exc()
+            print('上传文件错误: %s' % errorInfo)
+            return response.json(700, {'details': repr(e)})
+        else:
+            index = file_name.find('static/')
+            filePath = file_name[index:]
+            filePath = SERVER_DOMAIN + 'faq/image/' + filePath
+            # filePath = "http://192.168.136.35:8000/" + 'faq/image/' + filePath
+            return response.json(0, {'filePath': filePath})
+
+
+class getFAQImage(View):
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        filePath = kwargs.get('filePath', None)
+        filePath.encode(encoding='utf-8', errors='strict')
+        response = ResponseObject()
+        return self.getFile(filePath, response)
+
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'gb2312'
+        filePath = kwargs.get('filePath', None)
+        response = ResponseObject()
+        filePath.encode(encoding='gb2312', errors='strict')
+        return self.getFile(filePath, response)
+
+    def getFile(self, filePath, response):
+        if filePath:
+            pass
+        else:
+            return response.json(800)
+        fullPath = os.path.join(BASE_DIR, filePath).replace('\\', '/')
+
+        var_dump(fullPath)
+        if os.path.isfile(fullPath):
+            try:
+                Imagedata = open(fullPath, 'rb').read()
+            except Exception as e:
+                return response.json(906, repr(e))
+            else:
+                return HttpResponse(Imagedata, content_type="image/jpeg")
+        else:
+            return response.json(907)
+
+
+class FAQView(View):
+    @method_decorator(csrf_exempt)
+    def dispatch(self, *args, **kwargs):
+        return super(FAQView, self).dispatch(*args, **kwargs)
+
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        request_dict = request.POST
+        operation = kwargs.get('operation', None)
+        return self.validate(request_dict, operation)
+
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        request_dict = request.GET
+        operation = kwargs.get('operation', None)
+        return self.validate(request_dict, operation)
+
+    def validate(self, request_dict, operation):
+        token = TokenObject(request_dict.get('token', None))
+        response = ResponseObject()
+        if token.code != 0:
+            return response.json(token.code)
+
+        if operation == 'add':
+            return self.do_add(token, request_dict, response)
+        elif operation == 'query':
+            return self.do_query(token.userID, request_dict, response)
+        elif operation == 'update':
+            return self.do_update(token, request_dict, response)
+        elif operation == 'delete':
+            return self.do_delete(token.userID, request_dict, response)
+        else:
+            return response.json(404)
+
+    def do_add(self, token, request_dict, response):
+
+        own_permission = ModelService.check_perm(userID=token.userID, permID=120)
+        if own_permission is not True:
+            return response.json(404)
+
+        title = request_dict.get('title', None)
+        content = request_dict.get('content', None)
+
+        if title and content:
+            try:
+                # 对content中的图片路径进行修改
+                content = str(content)
+                content = content.replace('faq/image/static/FAQImages/tmp', 'faq/image/static/FAQImages')
+
+                # 取出redis中保存的此次上传的图片信息
+                redisObject = RedisObject()
+                images = redisObject.get_data(key=token.token)
+                if images is not False:
+                    images = json.loads(images)
+
+                    # 把图片从临时文件移动到FAQ资源文件夹下
+                    for k, v in images.items():
+                        start_index1 = v.find('tmp/')
+                        start_index2 = start_index1 + 4
+                        new_path = v[0:start_index1] + v[start_index2:]
+                        shutil.move(v, new_path)
+                now_time = int(time.time())
+                FAQModel.objects.create(**{
+                    'title': title,
+                    'content': content,
+                    'add_time': now_time,
+                    'update_time': now_time
+
+                })
+
+                # 删除redis中token对应的信息
+                redisObject.del_data(key=token.token)
+            except Exception as e:
+                print(e)
+                return response.json(174)
+
+            return response.json(0)
+        else:
+            return response.json(444)
+
+    def do_query(self, userID, request_dict, response):
+
+        page = request_dict.get('page', None)
+        line = request_dict.get('line', None)
+        search_key = request_dict.get('search_key', None)
+        if page and line:
+            if search_key:
+                own_permission = ModelService.check_perm(userID=userID, permID=110)
+                if own_permission is not True:
+                    return response.json(404)
+                faq_qs = FAQModel.objects.filter(title__contains=search_key)
+            else:
+                own_permission = ModelService.check_perm(userID=userID, permID=100)
+                if own_permission is not True:
+                    return response.json(404)
+
+                faq_qs = FAQModel.objects.filter()
+
+            if not faq_qs.exists():
+                return response.json(0, [])
+            count = faq_qs.count()
+            page = int(page)
+            line = int(line)
+            start = (page - 1) * line
+            end = start + line
+            faq_qs = faq_qs.values()[start:end]
+
+            return response.json(0, {'count': count, 'data': list(faq_qs)})
+        else:
+            return response.json(444)
+
+    def do_update(self, token, request_dict, response):
+        own_permission = ModelService.check_perm(userID=token.userID, permID=130)
+        if own_permission is not True:
+            return response.json(404)
+
+        id = request_dict.get('id', None)
+        title = request_dict.get('title', None)
+        content = request_dict.get('content', None)
+
+        if id:
+            now_time = int(time.time())
+            data = {
+                'update_time': now_time
+            }
+
+            if title:
+                data['title'] = title
+
+            if content:
+                content = str(content)
+                content = content.replace('faq/image/static/FAQImages/tmp', 'faq/image/static/FAQImages')
+
+                # 取出redis中保存的此次上传的图片信息
+                redisObject = RedisObject()
+                images = redisObject.get_data(key=token.token)
+                if images is not False:
+                    images = json.loads(images)
+
+                    # 把图片从临时文件移动到FAQ资源文件夹下
+                    for k, v in images.items():
+                        start_index1 = v.find('tmp/')
+                        start_index2 = start_index1 + 4
+                        new_path = v[0:start_index1] + v[start_index2:]
+                        shutil.move(v, new_path)
+                # 删除redis中token对应的信息
+                redisObject.del_data(key=token.token)
+
+                data['content'] = content
+
+            FAQModel.objects.filter(id=id).update(**data)
+
+            return response.json(0)
+        else:
+            return response.json(444)
+
+    def do_delete(self, userID, request_dict, response):
+
+        own_permission = ModelService.check_perm(userID=userID, permID=140)
+        if own_permission is not True:
+            return response.json(404)
+
+        id = request_dict.get('id', None)
+        if id:
+            try:
+                faq_qs = FAQModel.objects.filter(id=id)
+                faq_qs.delete()
+            except Exception as e:
+                print(e)
+                return response.json(173)
+            else:
+                return response.json(0)
+        else:
+            return response.json(444)

+ 6 - 3
Controller/TestApi.py

@@ -35,6 +35,7 @@ from django.http import JsonResponse, HttpResponseRedirect, HttpResponse
 from django.utils.decorators import method_decorator
 from django.views.decorators.csrf import csrf_exempt
 from django.views.generic.base import View
+from django.contrib.auth.hashers import make_password, check_password  # 对密码加密模块
 
 from Ansjer.config import OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET, OSS_ROLE_ARN, SERVER_DOMAIN, PAYPAL_CRD, \
     SERVER_DOMAIN_SSL
@@ -76,8 +77,8 @@ class testView(View):
         if operation is None:
             return response.json(444, 'error path')
         elif operation == 'tests':
-            userID  = '158943594633713800138000'
-            return self.do_filter_playlist(request_dict, userID, response)
+             res = make_password(123456)
+             return JsonResponse(status=200, data=res,safe=False)
         elif operation == 'cbu':
             return self.createBucket()
         elif operation == 'vodList':
@@ -92,12 +93,14 @@ class testView(View):
         elif operation == 'eqi_query':
             userID = '158943594633713800138000'
             return self.queryInterface(request_dict, userID, response)
+        elif operation == 'getAlexa':
+            userID = '158943594633713800138000'
+            return self.queryInterface(request_dict, userID, response)
         else:
             return 12344444
 
     def createBucket(self):
 
-
         #查看桶列表
         # url = "https://azvod1.s3-ap-northeast-1.amazonaws.com"
         # session = Session(ACCESS_KEY, SECRET_KEY)

+ 206 - 79
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
@@ -1753,7 +1754,7 @@ class v3LoginView(TemplateView):
         # 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]
+                               'phone', 'password', 'userIconPath', 'fingerprint_enable', 'fingerprint_key')[0]
         if not check_password(password, users['password']):
             return response.json(111)
         userID = users['userID']
@@ -1778,6 +1779,8 @@ class v3LoginView(TemplateView):
             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 ''
+            res['fingerprint_enable'] = users['fingerprint_enable']
+            res['fingerprint_key'] = CommonService.encode_data(content=users['fingerprint_key'], start=2)
             return response.json(0, res)
         else:
             return response.json(tko.code)
@@ -1953,6 +1956,7 @@ class wxAuthSignView(TemplateView):
                 'com.ansjer.loocamccloud': {'appid': 'wx9f6d6ce63f85b367',
                                             'secret': 'fe495884cd24637f1ae516c7f53d1b97', },
                 'com.ansjer.zccloud': {'appid': 'wx2a9f5ef9baf2760f', 'secret': '5d38c7079676463149ffea593c58f2ed'},
+                'com.ansjer.customizede': {'appid': 'wx2a9f5ef9baf2760f', 'secret': '5d38c7079676463149ffea593c58f2ed'},
                 # ios
                 'com.ansjer.zccloud_ab': {'appid': 'wx2a9f5ef9baf2760f', 'secret': '5d38c7079676463149ffea593c58f2ed'},
                 # android
@@ -2626,7 +2630,7 @@ class alexaUidView(TemplateView):
                 uid_list.append(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=1).values('uid', 'region_alexa')
+            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:
@@ -2927,81 +2931,80 @@ 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 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):
+        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):
@@ -3060,7 +3063,7 @@ class loginCodeView(View):
                 else:
                     sign_sms = 'Ansjer'
 
-                res = aliSms.send_code_sms(phone=phone, code=login_code, sign_name=sign_sms, temp_msg='SMS_151600991')
+                res = aliSms.send_code_sms(phone=phone, code=login_code, sign_name=sign_sms, temp_msg='SMS_151675022')
 
                 if res['Code'] == 'OK':
                     if redisObject.set_data(key=login_code_key, val=login_code, expire=300) is not True:
@@ -3164,3 +3167,127 @@ class v3LoginByCodeView(View):
             return response.json(0, res)
         else:
             return response.json(tko.code)
+
+
+class v3LoginByFingerprintView(View):
+    @method_decorator(csrf_exempt)  # @csrf_exempt
+    def dispatch(self, *args, **kwargs):
+        return super(v3LoginByFingerprintView, 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
+
+        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):
+        password = request_dict.get("password", None)
+
+        if password:
+            password = CommonService.decode_data(password)
+            if password is None:
+                return response.json(444)
+            else:
+                user_qs = Device_User.objects.filter(username=password, is_active=True, user_isValid=True)
+                if not user_qs.exists():
+                    return response.json(104)
+                else:
+                    users = user_qs.values('role__rid', 'role__roleName', 'userID', 'NickName', 'username', 'userEmail',
+                               'phone', 'password', 'userIconPath', 'fingerprint_enable', 'fingerprint_key')[0]
+                    if users['fingerprint_enable'] == 0:
+                        return response.json(112)
+                    else:
+                        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 ''
+                            res['fingerprint_enable'] = users['fingerprint_enable']
+                            res['fingerprint_key'] = CommonService.encode_data(content=users['fingerprint_key'], start=2)
+                            return response.json(0, res)
+                        else:
+                            return response.json(tko.code)
+        else:
+            return response.json(444)
+
+
+class v3SetFingerprintView(View):
+    @method_decorator(csrf_exempt)
+    def dispatch(self, *args, **kwargs):
+        return super(v3SetFingerprintView, self).dispatch(*args, **kwargs)
+
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        request_dict = request.POST
+        return self.validate(request_dict)
+
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        request_dict = request.GET
+        return self.validate(request_dict)
+
+    def validate(self, request_dict):
+        lang = request_dict.get('lang', None)
+        token = request_dict.get('token', None)
+        fingerprint_enable = request_dict.get('fingerprint_enable', None)
+        fingerprint_key = request_dict.get('fingerprint_key', None)
+
+        response = ResponseObject()
+
+        token = TokenObject(token)
+        if token.code != 0:
+            return response.json(token.code)
+
+        if not lang:
+            return response.json(444, 'lang')
+
+        response.lang = lang
+
+        data = {}
+
+        if fingerprint_enable:
+            data['fingerprint_enable'] = int(fingerprint_enable)
+
+        if fingerprint_key:
+            data['fingerprint_key'] = CommonService.decode_data(fingerprint_key, end=3)
+
+        if len(data) > 0:
+            Device_User.objects.filter(userID=token.userID).update(**data)
+        return response.json(0)

+ 26 - 0
Model/models.py

@@ -147,6 +147,8 @@ class Device_User(AbstractBaseUser):
     language = models.CharField(blank=True, max_length=16, default='en', verbose_name=u'语言地区')
     # 手机注册增加字段
     phone = models.CharField(max_length=16, verbose_name=u'手机号', default='', blank=True)
+    fingerprint_enable = models.SmallIntegerField(default=0, verbose_name=u'是否开启了指纹登录') # 0:未开启,1:已开启
+    fingerprint_key = models.CharField(max_length=128, default='', verbose_name=u'客户端用于解码的密钥等信息')
     objects = UserManager()
 
     USERNAME_FIELD = 'userID'  # 必须有一个唯一标识
@@ -947,3 +949,27 @@ class AppFrequencyYearStatisticsModel(models.Model):
         verbose_name = 'app使用频率统计表,年度统计'
         verbose_name_plural = verbose_name
         db_table = 'app_frequency_year_statistics'
+
+# alexa连接数统计表
+class AlexaConnectStatisticsModel(models.Model):
+    id = models.AutoField(primary_key=True)
+    num = models.IntegerField(default=0, verbose_name='总人数')
+    data_time = models.IntegerField(default=0, verbose_name='数据时间')
+
+    class Meta:
+        verbose_name = 'alexa连接数统计表'
+        verbose_name_plural = verbose_name
+        db_table = 'alexa_statistics'
+
+
+class FAQModel(models.Model):
+    id = models.AutoField(primary_key=True)
+    title = models.CharField(max_length=64, default='', unique=True, verbose_name='标题')
+    content = models.TextField(default='', verbose_name='内容')
+    add_time = models.IntegerField(default=0, verbose_name='添加时间')
+    update_time = models.IntegerField(default=0, verbose_name='更新时间')
+
+    class Meta:
+        db_table = 'tb_faq'
+        verbose_name = '问题帮助表'
+        verbose_name_plural = verbose_name

+ 2 - 0
Object/ResponseObject.py

@@ -31,6 +31,7 @@ class ResponseObject(object):
             109: 'The password not conform to the rules!',
             110: 'user doesn\'t activated',
             111: 'Error password',
+            112: 'Fingerprint login is not turned on',
             119: 'The qr code has expired',
             120: 'The code has expired',
             121: 'The verification code is wrong!',
@@ -93,6 +94,7 @@ class ResponseObject(object):
             109: '密码格式不符合!',
             110: '用户未激活!',
             111: '密码不正确!',
+            112: '未开通指纹登录',
             119: '二维码过期',
             120: '验证码过期',
             121: '验证码错了!',

+ 19 - 2
Service/CommonService.py

@@ -13,6 +13,9 @@ from Ansjer.config import BASE_DIR, UNICODE_ASCII_CHARACTER_SET
 
 
 # 复用性且公用较高封装代码在这
+from Controller.CheckUserData import RandomStr
+
+
 class CommonService:
     # 添加模糊搜索
     @staticmethod
@@ -225,9 +228,9 @@ class CommonService:
         return str
 
     @staticmethod
-    def decode_data(content):
+    def decode_data(content, start=1, end=4):
         try:
-            for i in range(1, 4):
+            for i in range(start, end):
                 if i == 1:
                     content = base64.b64decode(content)
                     content = content.decode('utf-8')
@@ -245,3 +248,17 @@ class CommonService:
         except Exception as e:
             print(e)
             return None
+
+    @staticmethod
+    def encode_data(content, start=1, end=4):
+        for i in range(start, end):
+            if i == 1:
+                content = RandomStr(3, False)+content+RandomStr(3, False)
+                content = base64.b64encode(str(content).encode("utf-8")).decode('utf8')
+            if i == 2:
+                content = RandomStr(2, False)+str(content)+RandomStr(2, False)
+                content = base64.b64encode(str(content).encode("utf-8")).decode('utf8')
+            if i == 3:
+                content = RandomStr(1, False)+str(content)+RandomStr(1, False)
+                content = base64.b64encode(str(content).encode("utf-8")).decode('utf8')
+        return content