60
+        return {
61
+            'nickname': self.nickname,
62
+            'avatar': self.avatar,
63
+        }

+ 7 - 0
guideline/tests.py

@@ -0,0 +1,7 @@
1
+# -*- coding: utf-8 -*-
2
+from __future__ import unicode_literals
3
+
4
+from django.test import TestCase
5
+
6
+
7
+# Create your tests here.

+ 7 - 0
guideline/views.py

@@ -0,0 +1,7 @@
1
+# -*- coding: utf-8 -*-
2
+from __future__ import unicode_literals
3
+
4
+from django.shortcuts import render
5
+
6
+
7
+# Create your views here.

+ 27 - 0
kodo/local_settings_dev.py

@@ -0,0 +1,27 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+import os
4
+
5
+
6
+BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
7
+PROJ_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__)))
8
+
9
+TEMPLATES = [
10
+    {
11
+        'BACKEND': 'django.template.backends.django.DjangoTemplates',
12
+        'DIRS': [os.path.join(BASE_DIR, 'templates')],
13
+        # 'APP_DIRS': True,
14
+        'OPTIONS': {
15
+            'context_processors': [
16
+                'django.template.context_processors.debug',
17
+                'django.template.context_processors.request',
18
+                'django.contrib.auth.context_processors.auth',
19
+                'django.contrib.messages.context_processors.messages',
20
+            ],
21
+            'loaders': [
22
+                'django.template.loaders.filesystem.Loader',
23
+                'django.template.loaders.app_directories.Loader',
24
+            ],
25
+        },
26
+    },
27
+]

+ 27 - 0
kodo/local_settings_dev_bak.py

@@ -0,0 +1,27 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+import os
4
+
5
+
6
+BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
7
+PROJ_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__)))
8
+
9
+TEMPLATES = [
10
+    {
11
+        'BACKEND': 'django.template.backends.django.DjangoTemplates',
12
+        'DIRS': [os.path.join(BASE_DIR, 'templates')],
13
+        # 'APP_DIRS': True,
14
+        'OPTIONS': {
15
+            'context_processors': [
16
+                'django.template.context_processors.debug',
17
+                'django.template.context_processors.request',
18
+                'django.contrib.auth.context_processors.auth',
19
+                'django.contrib.messages.context_processors.messages',
20
+            ],
21
+            'loaders': [
22
+                'django.template.loaders.filesystem.Loader',
23
+                'django.template.loaders.app_directories.Loader',
24
+            ],
25
+        },
26
+    },
27
+]

+ 10 - 0
kodo/settings.py

@@ -54,6 +54,7 @@ INSTALLED_APPS = (
54 54
     'box',
55 55
     'commands',
56 56
     'group',
57
+    'guideline',
57 58
     'integral',
58 59
     'logs',
59 60
     'mch',
@@ -390,11 +391,20 @@ KODO_DEFAULT_BRAND_NAME = ''
390 391
 KODO_DEFAULT_BRAND_DOMAIN = ''
391 392
 
392 393
 KODO_CLERK_AUTH_URL = 'http://pai.ai/w/o?r=http%3A%2F%2Fkodo.xfoto.com.cn%2Fp%2Fclerk%3Fbrand_id%3D{0}'
394
+KODO_SCREEN_AUTH_URL = 'http://pai.ai/w/o?r=http%3A%2F%2Fkodo.xfoto.com.cn%2Fp%2Fscreen%2Fadmin%2Foauth%3Fbrand_id%3D{0}'
395
+KODO_SCREEN_LOGIN_URL = 'http://pai.ai/w/o?s=snsapi_base&r=http%3A%2F%2Fkodo.xfoto.com.cn%2Fp%2Fscreen%2Fadmin%2Flogin/%3Fbrand_id%3D{0}%26token%3D{1}'
393 396
 
394 397
 # 经纬度
395 398
 GIS_2_ADMINISTRATIVE_DIVISION = 'http://116.196.105.215:1234/gis?auth_user=freevip&latitude={0}&longitude={1}'
396 399
 PHONE_2_ADMINISTRATIVE_DIVISION = 'https://www.baifubao.com/callback?cmd=1059&callback=phone&phone={0}'
397 400
 
401
+# 开发调试相关配置
402
+if DEBUG:
403
+    try:
404
+        from local_settings_dev import *
405
+    except ImportError:
406
+        pass
407
+
398 408
 try:
399 409
     from local_settings import *
400 410
 except ImportError:

+ 79 - 0
page/screen_views.py

@@ -0,0 +1,79 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+import shortuuid
4
+from django.conf import settings
5
+from django_response import response
6
+from json_render import json_render
7
+
8
+from guideline.models import ScreenAdminInfo
9
+from utils.error.errno_utils import PermissionStatusCode
10
+from utils.redis.connect import r
11
+from utils.redis.rkeys import KODO_SCREEN_ADMIN_LOGIN
12
+
13
+
14
+def screen_admin_oauthqr(request):
15
+    brand_id = request.GET.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
16
+
17
+    return json_render(request, 'page/screen_admin_oauth_qrcode.html', unjsondumpsdict={
18
+        'qr': settings.KODO_SCREEN_AUTH_URL.format(brand_id)
19
+    })
20
+
21
+
22
+def screen_admin_oauth(request):
23
+    brand_id = request.GET.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
24
+    unionid = request.GET.get('unionid', '')
25
+    openid = request.GET.get('openid', '')
26
+
27
+    ScreenAdminInfo.objects.update_or_create(brand_id=brand_id, unionid=unionid, openid=openid, defaults={
28
+        'nickname': request.GET.get('nickname', ''),
29
+        'avatar': request.GET.get('avatar', ''),
30
+        'user_status': ScreenAdminInfo.ACTIVATED,
31
+    })
32
+
33
+    return json_render(request, 'page/screen_admin_oauth_success.html', unjsondumpsdict={
34
+    })
35
+
36
+
37
+def screen_admin_loginqr(request):
38
+    brand_id = request.GET.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
39
+
40
+    token = shortuuid.uuid()
41
+
42
+    return response(200, {
43
+        'qr': settings.KODO_SCREEN_LOGIN_URL.format(brand_id, token),
44
+        'token': token,
45
+    })
46
+
47
+
48
+def screen_admin_login(request):
49
+    brand_id = request.GET.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
50
+    unionid = request.GET.get('unionid', '')
51
+    openid = request.GET.get('openid', '')
52
+    token = request.GET.get('token', '')
53
+
54
+    try:
55
+        admin = ScreenAdminInfo.objects.get(unionid=unionid, user_status=ScreenAdminInfo.ACTIVATED)
56
+    except ScreenAdminInfo.DoesNotExist:
57
+        return json_render(request, 'page/screen_admin_login_fail.html', unjsondumpsdict={
58
+        })
59
+
60
+    r.setex(KODO_SCREEN_ADMIN_LOGIN % (brand_id, token), r.REDIS_EXPIRED_HALF_HOUR, unionid)
61
+
62
+    return json_render(request, 'page/screen_admin_login_success.html', unjsondumpsdict={
63
+    })
64
+
65
+
66
+def screen_admin_loginrst(request):
67
+    brand_id = request.GET.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
68
+    token = request.GET.get('token', '')
69
+
70
+    unionid = r.get(KODO_SCREEN_ADMIN_LOGIN % (brand_id, token))
71
+
72
+    try:
73
+        admin = ScreenAdminInfo.objects.get(unionid=unionid, user_status=ScreenAdminInfo.ACTIVATED)
74
+    except ScreenAdminInfo.DoesNotExist:
75
+        return response(PermissionStatusCode.PERMISSION_DENIED)
76
+
77
+    return response(200, {
78
+        'info': admin.data,
79
+    })

+ 12 - 0
page/templates/page/screen_admin_login_fail.html

@@ -0,0 +1,12 @@
1
+<!DOCTYPE html>
2
+<html lang="en">
3
+<head>
4
+    <meta charset="UTF-8">
5
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+    <meta http-equiv="X-UA-Compatible" content="ie=edge">
7
+    <title>登录失败</title>
8
+</head>
9
+<body>
10
+    <div class="" style="text-align:center;margin-top:100px;font-size:25px;">登录失败</div>
11
+</body>
12
+</html>

+ 12 - 0
page/templates/page/screen_admin_login_success.html

@@ -0,0 +1,12 @@
1
+<!DOCTYPE html>
2
+<html lang="en">
3
+<head>
4
+    <meta charset="UTF-8">
5
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+    <meta http-equiv="X-UA-Compatible" content="ie=edge">
7
+    <title>登录成功</title>
8
+</head>
9
+<body>
10
+    <div class="" style="text-align:center;margin-top:100px;font-size:25px;">登录成功</div>
11
+</body>
12
+</html>

+ 64 - 0
page/templates/page/screen_admin_oauth_qrcode.html

@@ -0,0 +1,64 @@
1
+{% load staticfiles %}
2
+
3
+<!DOCTYPE html>
4
+<html lang="zh-CN">
5
+    <head>
6
+        <meta charset="utf-8">
7
+        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
8
+        <meta name="format-detection" content="telephone=no,email=no,address=no">
9
+        <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">
10
+        <title>授权登录二维码</title>
11
+
12
+        <link href="//res.wx.qq.com/open/libs/weui/0.4.3/weui.min.css" rel="stylesheet" type="text/css" />
13
+
14
+        <style>
15
+            input:required:invalid {
16
+                color: #E64340;
17
+            }
18
+            input:required:valid {
19
+                color: rgb(0, 0, 0);
20
+            }
21
+            .hidden {
22
+                display: none;
23
+            }
24
+            .qr {
25
+                position: fixed;
26
+                left: 50%;
27
+                top: 50%;
28
+                margin-left: -100px;
29
+                margin-top: -100px;
30
+                padding: 5px 5px 0 5px;
31
+                border: 1px solid #000;
32
+                border-radius: 5px;
33
+            }
34
+        </style>
35
+    </head>
36
+    <body>
37
+        <div class="container" >
38
+            <img id="qr_logo" class="hidden" src="{% static 'kodo/img/paiai_96_96.png' %}">
39
+            <div id="qr" class="qr"></div>
40
+        </div>
41
+
42
+        <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
43
+        <script src="//cdnjs.cloudflare.com/ajax/libs/lrsjng.jquery-qrcode/0.14.0/jquery-qrcode.min.js"></script>
44
+        <script>
45
+            $("#qr").empty().qrcode({
46
+                render: 'canvas',
47
+                mode: 0,
48
+                text: '{{ qr }}'
49
+            });
50
+        </script>
51
+        <script type="text/javascript" src="//res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
52
+        <script type="text/javascript" src="{% static 'kodo/js/jswe-0.0.4.js' %}"></script>
53
+        <script>
54
+            V.initWxData({
55
+                imgUrl: "http://pai.ai/static/kodo/img/paiai_96_96.png",
56
+                link: 'http://pai.ai/w/o?r=http%3A%2F%2Fpai.ai%2Fp%2Floginqr',
57
+                desc: "授权登录",
58
+                title: "授权登录",
59
+                timeLine: ""
60
+            }, true);
61
+            V.hideOptionMenu();
62
+        </script>
63
+    </body>
64
+</html>

+ 13 - 0
page/templates/page/screen_admin_oauth_success.html

@@ -0,0 +1,13 @@
1
+<!DOCTYPE html>
2
+<html lang="en">
3
+<head>
4
+    <meta charset="UTF-8">
5
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+    <meta http-equiv="X-UA-Compatible" content="ie=edge">
7
+    <title>授权成功</title>
8
+</head>
9
+<body>
10
+    <div class="" style="text-align:center;margin-top:100px;font-size:25px;">授权成功</div>
11
+    <div class="" style="text-align:center;font-size:15px;">请扫描统揽大屏二维码开启大屏</div>
12
+</body>
13
+</html>

+ 7 - 1
page/urls.py

@@ -4,7 +4,7 @@ from django.conf.urls import url
4 4
 
5 5
 from account import tourguide_views
6 6
 from group import lensman_views
7
-from page import info_views, oauth_views, page_views, sale_views
7
+from page import info_views, oauth_views, page_views, sale_views, screen_views
8 8
 
9 9
 
10 10
 urlpatterns = [
@@ -33,3 +33,9 @@ urlpatterns = [
33 33
     url(r'^clerk$', oauth_views.clerk_oauth, name='clerk_oauth'),  # 店员授权页面
34 34
     url(r'^clerk/info$', info_views.clerk_info_oauth, name='clerk_info_oauth'),  # 店员信息授权页面
35 35
 ]
36
+
37
+urlpatterns += [
38
+    url(r'^qr$', screen_views.screen_admin_oauthqr, name='oauthqr'),
39
+    url(r'^screen/admin/oauth$', screen_views.screen_admin_oauth, name='screen_admin_oauth'),
40
+    url(r'^screen/admin/login$', screen_views.screen_admin_login, name='screen_admin_login'),
41
+]

+ 1 - 1
requirements_dj.txt

@@ -2,7 +2,7 @@ Django==1.11.16
2 2
 django-admin==1.3.2
3 3
 django-cors-headers==2.4.0
4 4
 django-curtail-uuid==1.0.4
5
-django-detect==1.0.6
5
+django-detect==1.0.8
6 6
 django-file-md5==1.0.2
7 7
 django-file-upload==1.1.0
8 8
 django-ip==1.0.2

+ 5 - 0
utils/error/errno_utils.py

@@ -187,3 +187,8 @@ class TokenStatusCode(BaseStatusCode):
187 187
     """ 票据相关错误码 4090xx """
188 188
     TOKEN_NOT_FOUND = StatusCodeField(409901, 'Token Not Found', description=u'票据不存在')
189 189
     TOKEN_HAS_EXPIRED = StatusCodeField(409911, 'Token Has Expired', description=u'票据过期,请刷新重扫二维码')
190
+
191
+
192
+class PermissionStatusCode(BaseStatusCode):
193
+    """ 4099xx 权限相关错误码 """
194
+    PERMISSION_DENIED = StatusCodeField(409900, 'Permission Denied', description=u'权限不足')

+ 2 - 0
utils/redis/rkeys.py

@@ -69,3 +69,5 @@ BOX_PROGRAM_VERSION_INFO = 'box:program:version:info'  # STRING,BOX 程序版
69 69
 
70 70
 # 小程序相关
71 71
 MINI_PROGRAM_GIS_LIST = 'tamron:miniprogram:gis:list'
72
+
73
+KODO_SCREEN_ADMIN_LOGIN = 'kodo:screen:admin:login:%s:%s'  # brand_id, token

登錄 - Gogs: Go Git Service

登錄