:art: Mini

huangqimin001 3 years ago
parent
commit
0c4145c394

+ 6 - 1
account/admin.py

@@ -5,10 +5,14 @@ from django.contrib import admin
5 5
 from django.contrib.auth.hashers import make_password
6 6
 from pysnippets.strsnippets import strip
7 7
 
8
-from account.models import AdministratorInfo
8
+from account.models import AdministratorInfo, UserInfo
9 9
 from equipment.models import IsolationPointInfo
10 10
 
11 11
 
12
+class UserInfoAdmin(admin.ModelAdmin):
13
+    list_display = ('user_id', 'unionid', 'openid', 'openid_miniapp', 'name', 'sex', 'nickname', 'avatar', 'phone', 'country', 'province', 'city', 'user_status', 'updated_at', 'created_at')
14
+
15
+
12 16
 class AdministratorInfoAdmin(admin.ModelAdmin):
13 17
     list_display = ('admin_id', 'phone', 'password', 'encryption', 'name', 'point_id', 'point_name', 'user_status', 'status', 'created_at', 'updated_at')
14 18
     list_filter = ('user_status', 'status', 'point_name')
@@ -30,4 +34,5 @@ class AdministratorInfoAdmin(admin.ModelAdmin):
30 34
         obj.save()
31 35
 
32 36
 
37
+admin.site.register(UserInfo, UserInfoAdmin)
33 38
 admin.site.register(AdministratorInfo, AdministratorInfoAdmin)

+ 40 - 0
account/migrations/0002_userinfo.py

@@ -0,0 +1,40 @@
1
+# Generated by Django 3.2.6 on 2021-08-12 05:49
2
+
3
+from django.db import migrations, models
4
+import shortuuidfield.fields
5
+
6
+
7
+class Migration(migrations.Migration):
8
+
9
+    dependencies = [
10
+        ('account', '0001_initial'),
11
+    ]
12
+
13
+    operations = [
14
+        migrations.CreateModel(
15
+            name='UserInfo',
16
+            fields=[
17
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
18
+                ('status', models.BooleanField(default=True, help_text='Status', verbose_name='status')),
19
+                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')),
20
+                ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')),
21
+                ('user_id', shortuuidfield.fields.ShortUUIDField(blank=True, db_index=True, editable=False, help_text='用户唯一标识', max_length=22, null=True, unique=True)),
22
+                ('unionid', models.CharField(blank=True, db_index=True, help_text='微信 Unionid', max_length=32, null=True, unique=True, verbose_name='unionid')),
23
+                ('openid', models.CharField(blank=True, db_index=True, help_text='微信公众号 Openid', max_length=32, null=True, unique=True, verbose_name='openid')),
24
+                ('openid_miniapp', models.CharField(blank=True, db_index=True, help_text='微信小程序 Openid', max_length=32, null=True, unique=True, verbose_name='openid_miniapp')),
25
+                ('name', models.CharField(blank=True, help_text='用户姓名', max_length=255, null=True, verbose_name='name')),
26
+                ('sex', models.IntegerField(choices=[(0, '未知'), (1, '男'), (2, '女')], default=0, help_text='用户性别', verbose_name='sex')),
27
+                ('nickname', models.CharField(blank=True, help_text='用户昵称', max_length=255, null=True, verbose_name='nickname')),
28
+                ('avatar', models.CharField(blank=True, help_text='用户头像', max_length=255, null=True, verbose_name='avatar')),
29
+                ('phone', models.CharField(blank=True, db_index=True, help_text='用户电话', max_length=11, null=True, verbose_name='phone')),
30
+                ('country', models.CharField(blank=True, help_text='用户国家', max_length=255, null=True, verbose_name='country')),
31
+                ('province', models.CharField(blank=True, help_text='用户省份', max_length=255, null=True, verbose_name='province')),
32
+                ('city', models.CharField(blank=True, help_text='用户城市', max_length=255, null=True, verbose_name='city')),
33
+                ('user_status', models.IntegerField(choices=[(0, '未验证'), (1, '已激活'), (2, '已禁用'), (3, '已删除'), (10, '已分配')], default=0, help_text='用户状态', verbose_name='user_status')),
34
+            ],
35
+            options={
36
+                'verbose_name': '用户信息',
37
+                'verbose_name_plural': '用户信息',
38
+            },
39
+        ),
40
+    ]

+ 61 - 1
account/models.py

@@ -2,10 +2,70 @@
2 2
 
3 3
 from django.db import models
4 4
 from django.utils.translation import ugettext_lazy as _
5
-from django_models_ext import BaseModelMixin
5
+from django_models_ext import BaseModelMixin, SexModelMixin
6 6
 from shortuuidfield import ShortUUIDField
7 7
 
8 8
 
9
+class UserInfo(BaseModelMixin):
10
+    UNVERIFIED = 0
11
+    ACTIVATED = 1
12
+    DISABLED = 2
13
+    DELETED = 3
14
+    ASSIGN = 10
15
+
16
+    USER_STATUS = (
17
+        (UNVERIFIED, '未验证'),
18
+        (ACTIVATED, '已激活'),
19
+        (DISABLED, '已禁用'),
20
+        (DELETED, '已删除'),
21
+        (ASSIGN, '已分配'),
22
+    )
23
+
24
+    user_id = ShortUUIDField(_('user_id'), max_length=32, blank=True, null=True, help_text='用户唯一标识', db_index=True, unique=True)
25
+
26
+    # 微信授权用户
27
+    unionid = models.CharField(_('unionid'), max_length=32, blank=True, null=True, help_text='微信 Unionid', db_index=True, unique=True)
28
+    openid = models.CharField(_('openid'), max_length=32, blank=True, null=True, help_text='微信公众号 Openid', db_index=True, unique=True)
29
+    openid_miniapp = models.CharField(_('openid_miniapp'), max_length=32, blank=True, null=True, help_text='微信小程序 Openid', db_index=True, unique=True)
30
+
31
+    # 用户基本信息
32
+    name = models.CharField(_('name'), max_length=255, blank=True, null=True, help_text='用户姓名')
33
+    sex = models.IntegerField(_('sex'), choices=SexModelMixin.SEX_TUPLE, default=SexModelMixin.UNKNOWN, help_text='用户性别')
34
+    nickname = models.CharField(_('nickname'), max_length=255, blank=True, null=True, help_text='用户昵称')
35
+    avatar = models.CharField(_('avatar'), max_length=255, blank=True, null=True, help_text='用户头像')
36
+    phone = models.CharField(_('phone'), max_length=11, blank=True, null=True, help_text='用户电话', db_index=True)
37
+    country = models.CharField(_('country'), max_length=255, blank=True, null=True, help_text='用户国家')
38
+    province = models.CharField(_('province'), max_length=255, blank=True, null=True, help_text='用户省份')
39
+    city = models.CharField(_('city'), max_length=255, blank=True, null=True, help_text='用户城市')
40
+
41
+    user_status = models.IntegerField(_('user_status'), choices=USER_STATUS, default=UNVERIFIED, help_text='用户状态')
42
+
43
+    class Meta:
44
+        verbose_name = _('用户信息')
45
+        verbose_name_plural = _('用户信息')
46
+
47
+    def __unicode__(self):
48
+        return '%d' % self.pk
49
+
50
+    @property
51
+    def data(self):
52
+        return {
53
+            'user_id': self.user_id,
54
+            'unionid': self.unionid,
55
+            'openid': self.openid,
56
+            'openid_miniapp': self.openid_miniapp,
57
+            'name': self.name,
58
+            'sex': self.sex,
59
+            'nickname': self.nickname,
60
+            'avatar': self.avatar,
61
+            'phone': self.phone,
62
+            'country': self.country,
63
+            'province': self.province,
64
+            'city': self.city,
65
+            'user_status': self.user_status,
66
+        }
67
+
68
+
9 69
 class AdministratorInfo(BaseModelMixin):
10 70
     ACTIVATED = 1
11 71
     DISABLED = 2

+ 10 - 3
api/eqpt_views.py

@@ -12,8 +12,8 @@ from django_response import response
12 12
 from paginator import pagination
13 13
 from TimeConvert import TimeConvert as tc
14 14
 
15
-from equipment.models import (IsolationPointInfo, ThermometerEquipmentInfo, ThermometerMeasureInfo,
16
-                              ThermometerMeasureLogInfo)
15
+from equipment.models import (IsolationPointInfo, IsolationPointUserInfo, ThermometerEquipmentInfo,
16
+                              ThermometerMeasureInfo, ThermometerMeasureLogInfo)
17 17
 from utils.age import stamp2age
18 18
 from utils.error.errno_utils import IsolationPointStatusCode, ThermometerEquipmentStatusCode
19 19
 
@@ -135,6 +135,9 @@ def eqpt_result(request):
135 135
     ).values('macid', 'temperature')
136 136
     logs = {log.get('macid'): log.get('temperature') for log in logs}
137 137
 
138
+    infos = IsolationPointUserInfo.objects.filter(point_id=point_id, status=True).values('pk', 'fields')
139
+    infos = {info.get('pk'): info.get('fields') for info in infos}
140
+
138 141
     total_active_eqpt_num = eqpts.count()
139 142
     has_upload_temperature_num = len(logs)
140 143
     temperature_over_375 = len([1 for temperature in logs.values() if temperature > 37.5])
@@ -142,7 +145,11 @@ def eqpt_result(request):
142 145
     if kw:
143 146
         eqpts = eqpts.filter(Q(name__icontains=kw) | Q(phone__icontains=kw))
144 147
     eqpts, left = pagination(eqpts, page, num)
145
-    eqpts = [{**eqpt.data, **{'has_upload': eqpt.macid in logs, 'temperature': logs.get(eqpt.macid, 0)}} for eqpt in eqpts]
148
+    eqpts = [{**eqpt.data, **{
149
+        'has_upload': eqpt.macid in logs,
150
+        'temperature': logs.get(eqpt.macid, 0),
151
+        'fields': infos.get(eqpt.ipui_pk, {}),
152
+    }} for eqpt in eqpts]
146 153
 
147 154
     return response(data={
148 155
         'eqpts': eqpts,

+ 168 - 0
api/mini_views.py

@@ -0,0 +1,168 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+import logging
4
+
5
+from django.conf import settings
6
+from django.db import transaction
7
+from django_logit import logit
8
+from django_response import response
9
+from pywe_miniapp import get_session_info, get_session_key, get_userinfo, store_session_key
10
+from pywe_storage import RedisStorage
11
+
12
+from account.models import UserInfo
13
+from utils.redis.connect import r
14
+
15
+
16
+WECHAT = settings.WECHAT
17
+logger = logging.getLogger('logit')
18
+
19
+
20
+@logit
21
+@transaction.atomic
22
+def get_userinfo_api(request):
23
+    appId = request.POST.get('appId', 'MINIAPP')
24
+
25
+    wxcfg = WECHAT.get(appId, {})
26
+
27
+    appid = wxcfg.get('appID')
28
+    secret = wxcfg.get('appsecret')
29
+
30
+    code = request.POST.get('code', '')
31
+    encryptedData = request.POST.get('encryptedData', '')
32
+    iv = request.POST.get('iv', '')
33
+
34
+    # {u'avatarUrl': u'http://wx.qlogo.cn/mmopen/vi_32/aSKcBBPpibyKNicHNTMM0qJVh8Kjgiak2AHWr8MHM4WgMEm7GFhsf8OYrySdbvAMvTsw3mo8ibKicsnfN5pRjl1p8HQ/0',
35
+    #  u'city': u'Guangzhou',
36
+    #  u'country': u'CN',
37
+    #  u'gender': 1,
38
+    #  u'language': u'zh_CN',
39
+    #  u'nickName': u'Band',
40
+    #  u'openId': u'oGZUI0egBJY1zhBYw2KhdUfwVJJE',
41
+    #  u'province': u'Guangdong',
42
+    #  u'unionId': u'ocMvos6NjeKLIBqg5Mr9QjxrP1FA',
43
+    #  u'watermark': {u'appid': u'wx4f4bc4dec97d474b', u'timestamp': 1477314187}}
44
+    session_key = get_session_key(appid=appid, secret=secret, code=code)
45
+    # Get Userinfo
46
+    userinfo = get_userinfo(appid=appid, secret=secret, code=code, session_key=session_key, encryptedData=encryptedData, iv=iv)
47
+
48
+    # Get or Create User
49
+    user, created = UserInfo.objects.select_for_update().get_or_create(unionid=userinfo.get('unionId', ''))
50
+
51
+    # Set User Key's Value
52
+    user.unionid = userinfo.get('unionId', '')
53
+    user.openid_miniapp = userinfo.get('openId', '')
54
+    user.sex = userinfo.get('gender', '')
55
+    user.nickname = userinfo.get('nickName', '')
56
+    user.avatar = userinfo.get('avatarUrl', '')
57
+    user.country = userinfo.get('country', '')
58
+    user.province = userinfo.get('province', '')
59
+    user.city = userinfo.get('city', '')
60
+    user.user_status = UserInfo.ACTIVATED
61
+    user.save()
62
+
63
+    # Store SessionKey
64
+    store_session_key(appid=appid, secret=secret, session_key=session_key, unid=user.user_id, storage=RedisStorage(r))
65
+    # Just for compatible because of store session_key has changed
66
+    store_session_key(appid=appid, secret=secret, session_key=session_key, unid='', storage=RedisStorage(r))
67
+
68
+    return response(200, 'Mini App Login Success', '微信小程序登录成功', user.data)
69
+
70
+
71
+@logit(res=True)
72
+@transaction.atomic
73
+def mini_login_api(request):
74
+    appId = request.POST.get('appId', 'MINIAPP')
75
+
76
+    wxcfg = WECHAT.get(appId, {})
77
+
78
+    appid = wxcfg.get('appID')
79
+    secret = wxcfg.get('appsecret')
80
+
81
+    code = request.POST.get('code', '')
82
+
83
+    # // 正常返回的JSON数据包
84
+    # {
85
+    #     "openid": "OPENID",
86
+    #     "session_key": "SESSIONKEY",
87
+    # }
88
+    #
89
+    # // 满足UnionID返回条件时,返回的JSON数据包
90
+    # {
91
+    #     "openid": "OPENID",
92
+    #     "session_key": "SESSIONKEY",
93
+    #     "unionid": "UNIONID"
94
+    # }
95
+    # // 错误时返回JSON数据包(示例为Code无效)
96
+    # {
97
+    #     "errcode": 40029,
98
+    #     "errmsg": "invalid code"
99
+    # }
100
+    session_info = get_session_info(appid=appid, secret=secret, code=code)
101
+    logger.debug(session_info)
102
+    session_key = session_info.get('session_key', '')
103
+    unionid = session_info.get('unionid', '')
104
+    openid = session_info.get('openid', '')
105
+
106
+    # Get or Create User
107
+    user, created = UserInfo.objects.select_for_update().get_or_create(openid_miniapp=openid)
108
+
109
+    # Set User Key's Value
110
+    if unionid:
111
+        user.unionid = unionid
112
+
113
+    user.user_status = UserInfo.ACTIVATED
114
+    user.save()
115
+
116
+    # Store SessionKey
117
+    store_session_key(appid=appid, secret=secret, session_key=session_key, unid=user.user_id, storage=RedisStorage(r))
118
+    # Just for compatible because of store session_key has changed
119
+    store_session_key(appid=appid, secret=secret, session_key=session_key, unid='', storage=RedisStorage(r))
120
+
121
+    return response(200, 'Mini App Login Success', '微信小程序登录成功', user.data)
122
+
123
+
124
+@logit
125
+@transaction.atomic
126
+def get_userinfo_api2(request):
127
+    user_id = request.POST.get('user_id', '')
128
+    appId = request.POST.get('appId', 'MINIAPP')
129
+
130
+    wxcfg = WECHAT.get(appId, {})
131
+
132
+    appid = wxcfg.get('appID')
133
+    secret = wxcfg.get('appsecret')
134
+
135
+    encryptedData = request.POST.get('encryptedData', '')
136
+    iv = request.POST.get('iv', '')
137
+
138
+    try:
139
+        user = UserInfo.objects.select_for_update().get(user_id=user_id, status=True)
140
+    except UserInfo.DoesNotExist:
141
+        return response()
142
+
143
+    # {u'avatarUrl': u'http://wx.qlogo.cn/mmopen/vi_32/aSKcBBPpibyKNicHNTMM0qJVh8Kjgiak2AHWr8MHM4WgMEm7GFhsf8OYrySdbvAMvTsw3mo8ibKicsnfN5pRjl1p8HQ/0',
144
+    #  u'city': u'Guangzhou',
145
+    #  u'country': u'CN',
146
+    #  u'gender': 1,
147
+    #  u'language': u'zh_CN',
148
+    #  u'nickName': u'Band',
149
+    #  u'openId': u'oGZUI0egBJY1zhBYw2KhdUfwVJJE',
150
+    #  u'province': u'Guangdong',
151
+    #  u'unionId': u'ocMvos6NjeKLIBqg5Mr9QjxrP1FA',
152
+    #  u'watermark': {u'appid': u'wx4f4bc4dec97d474b', u'timestamp': 1477314187}}
153
+    session_key = get_session_key(appid=appid, secret=secret, unid=user_id, storage=RedisStorage(r))
154
+    # Get Userinfo
155
+    userinfo = get_userinfo(appid=appid, secret=secret, session_key=session_key, encryptedData=encryptedData, iv=iv)
156
+
157
+    # Set User Key's Value
158
+    user.unionid = userinfo.get('unionId', '')
159
+    user.openid_miniapp = userinfo.get('openId', '')
160
+    user.sex = userinfo.get('gender', '')
161
+    user.nickname = userinfo.get('nickName', '')
162
+    user.avatar = userinfo.get('avatarUrl', '')
163
+    user.country = userinfo.get('country', '')
164
+    user.province = userinfo.get('province', '')
165
+    user.city = userinfo.get('city', '')
166
+    user.save()
167
+
168
+    return response(200, 'Mini App Get Userinfo Success', '微信小程序获取用户信息成功', user.data)

+ 44 - 1
api/point_views.py

@@ -6,7 +6,7 @@ from django_logit import logit
6 6
 from django_query import get_query_value
7 7
 from django_response import response
8 8
 
9
-from equipment.models import IsolationPointInfo
9
+from equipment.models import IsolationPointInfo, IsolationPointUserInfo, ThermometerEquipmentInfo
10 10
 from utils.error.errno_utils import IsolationPointStatusCode
11 11
 
12 12
 
@@ -24,3 +24,46 @@ def measure_window(request):
24 24
     point.save()
25 25
 
26 26
     return response()
27
+
28
+
29
+@logit
30
+def get_point_fields(request):
31
+    point_id = request.POST.get('point_id', '')
32
+
33
+    try:
34
+        point = IsolationPointInfo.objects.get(point_id=point_id, status=True)
35
+    except IsolationPointInfo.DoesNotExist:
36
+        return response(IsolationPointStatusCode.ISOLATIONPOINT_NOT_FOUND)
37
+
38
+    return response(data={
39
+        'fields': point.point_fields,
40
+    })
41
+
42
+
43
+@logit
44
+def save_point_fields(request):
45
+    point_id = request.POST.get('point_id', '')
46
+    user_id = request.POST.get('user_id', '')
47
+    fields = get_query_value(request, 'fields', val_cast_type='listjson')
48
+
49
+    IsolationPointUserInfo.objects.create(point_id=point_id, user_id=user_id, fields=fields)
50
+
51
+    return response()
52
+
53
+
54
+@logit
55
+def bind_eqpt(request):
56
+    macid = request.POST.get('macid', '')
57
+    point_id = request.POST.get('point_id', '')
58
+    user_id = request.POST.get('user_id', '')
59
+
60
+    try:
61
+        ipui = IsolationPointUserInfo.objects.get(point_id=point_id, user_id=user_id, status=True)
62
+    except IsolationPointUserInfo.DoesNotExist:
63
+        return response()
64
+
65
+    ThermometerEquipmentInfo.objects.update_or_create(macid=macid, defaults={
66
+        'ipui_pk': ipui.pk,
67
+    })
68
+
69
+    return response()

+ 14 - 1
api/urls.py

@@ -2,7 +2,7 @@
2 2
 
3 3
 from django.conf.urls import url
4 4
 
5
-from api import admin_views, eqpt_views, oauth_views, point_views
5
+from api import admin_views, eqpt_views, mini_views, oauth_views, point_views
6 6
 
7 7
 
8 8
 urlpatterns = [
@@ -31,3 +31,16 @@ urlpatterns += [
31 31
 urlpatterns += [
32 32
     url(r'^upload/temperature$', eqpt_views.upload_temperature, name='upload_temperature'),
33 33
 ]
34
+
35
+# Mini App
36
+urlpatterns += [
37
+    url(r'^mp/userinfo$', mini_views.get_userinfo_api, name='get_userinfo_api'),  # 获取用户信息
38
+    url(r'^mp/login$', mini_views.mini_login_api, name='mini_login_api'),  # 小程序登录
39
+    url(r'^mp/userinfo2$', mini_views.get_userinfo_api2, name='get_userinfo_api2'),  # 获取用户信息
40
+]
41
+
42
+urlpatterns += [
43
+    url(r'^mp/get_point_fields$', point_views.get_point_fields, name='get_point_fields'),
44
+    url(r'^mp/save_point_fields$', point_views.save_point_fields, name='save_point_fields'),
45
+    url(r'^mp/bind_eqpt$', point_views.bind_eqpt, name='bind_eqpt'),
46
+]

+ 1 - 0
commands/management/commands/mqtt.py

@@ -6,6 +6,7 @@ import time
6 6
 
7 7
 from django_six import CompatibilityBaseCommand
8 8
 from paho.mqtt import client as mqtt_client
9
+
9 10
 from api.eqpt_views import mqtt_upload_temperature
10 11
 
11 12
 

+ 9 - 4
equipment/admin.py

@@ -3,16 +3,20 @@
3 3
 from django.contrib import admin
4 4
 from django_admin import ReadOnlyModelAdmin
5 5
 
6
-from equipment.models import (IsolationPointInfo, ThermometerEquipmentInfo, ThermometerMeasureInfo,
7
-                              ThermometerMeasureLogInfo)
6
+from equipment.models import (IsolationPointInfo, IsolationPointUserInfo, ThermometerEquipmentInfo,
7
+                              ThermometerMeasureInfo, ThermometerMeasureLogInfo)
8 8
 
9 9
 
10 10
 class IsolationPointInfoAdmin(admin.ModelAdmin):
11
-    list_display = ('point_id', 'point_name', 'point_measure_window', 'status', 'updated_at', 'created_at')
11
+    list_display = ('point_id', 'point_name', 'point_measure_window', 'point_fields', 'limit_scene_qrcode_url', 'status', 'updated_at', 'created_at')
12
+
13
+
14
+class IsolationPointUserInfoAdmin(admin.ModelAdmin):
15
+    list_display = ('point_id', 'user_id', 'fields', 'status', 'updated_at', 'created_at')
12 16
 
13 17
 
14 18
 class ThermometerEquipmentInfoAdmin(ReadOnlyModelAdmin, admin.ModelAdmin):
15
-    list_display = ('eqpt_id', 'point_id', 'macid', 'sn', 'active_status', 'active_at', 'name', 'sex', 'birth_stamp', 'age', 'phone', 'remark', 'last_submit_at', 'eqpt_register_status', 'eqpt_register_result', 'status', 'updated_at', 'created_at')
19
+    list_display = ('eqpt_id', 'point_id', 'macid', 'sn', 'active_status', 'active_at', 'ipui_pk', 'name', 'sex', 'birth_stamp', 'age', 'phone', 'remark', 'last_submit_at', 'eqpt_register_status', 'eqpt_register_result', 'status', 'updated_at', 'created_at')
16 20
     list_filter = ('point_id', 'status')
17 21
 
18 22
 
@@ -27,6 +31,7 @@ class ThermometerMeasureLogInfoAdmin(ReadOnlyModelAdmin, admin.ModelAdmin):
27 31
 
28 32
 
29 33
 admin.site.register(IsolationPointInfo, IsolationPointInfoAdmin)
34
+admin.site.register(IsolationPointUserInfo, IsolationPointUserInfoAdmin)
30 35
 admin.site.register(ThermometerEquipmentInfo, ThermometerEquipmentInfoAdmin)
31 36
 admin.site.register(ThermometerMeasureInfo, ThermometerMeasureInfoAdmin)
32 37
 admin.site.register(ThermometerMeasureLogInfo, ThermometerMeasureLogInfoAdmin)

+ 46 - 0
equipment/migrations/0006_auto_20210812_1357.py

@@ -0,0 +1,46 @@
1
+# Generated by Django 3.2.6 on 2021-08-12 05:57
2
+
3
+from django.db import migrations, models
4
+import jsonfield.fields
5
+
6
+
7
+class Migration(migrations.Migration):
8
+
9
+    dependencies = [
10
+        ('equipment', '0005_thermometermeasureloginfo_temperature_src'),
11
+    ]
12
+
13
+    operations = [
14
+        migrations.AddField(
15
+            model_name='isolationpointinfo',
16
+            name='limit_scene_qrcode_url',
17
+            field=models.CharField(blank=True, help_text='字段二维码', max_length=255, null=True, verbose_name='limit_scene_qrcode_url'),
18
+        ),
19
+        migrations.AddField(
20
+            model_name='isolationpointinfo',
21
+            name='point_fields',
22
+            field=jsonfield.fields.JSONField(blank=True, default=[], help_text='字段列表', null=True, verbose_name='point_fields'),
23
+        ),
24
+        migrations.AddField(
25
+            model_name='thermometerequipmentinfo',
26
+            name='ipui_pk',
27
+            field=models.IntegerField(default=0, help_text='隔离点用户录入PK', verbose_name='ipui_pk'),
28
+        ),
29
+        migrations.CreateModel(
30
+            name='IsolationPointUserInfo',
31
+            fields=[
32
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
33
+                ('status', models.BooleanField(default=True, help_text='Status', verbose_name='status')),
34
+                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')),
35
+                ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')),
36
+                ('point_id', models.CharField(blank=True, db_index=True, help_text='隔离点唯一标识', max_length=32, null=True, verbose_name='point_id')),
37
+                ('user_id', models.CharField(blank=True, db_index=True, help_text='用户唯一标识', max_length=32, null=True, verbose_name='user_id')),
38
+                ('fields', jsonfield.fields.JSONField(blank=True, default=[], help_text='字段信息', null=True, verbose_name='fields')),
39
+            ],
40
+            options={
41
+                'verbose_name': '隔离点用户录入信息',
42
+                'verbose_name_plural': '隔离点用户录入信息',
43
+                'unique_together': {('point_id', 'user_id')},
44
+            },
45
+        ),
46
+    ]

+ 39 - 0
equipment/models.py

@@ -11,9 +11,19 @@ from TimeConvert import TimeConvert as tc
11 11
 class IsolationPointInfo(BaseModelMixin):
12 12
     point_id = ShortUUIDField(_('point_id'), max_length=32, blank=True, null=True, help_text='隔离点唯一标识', db_index=True, unique=True)
13 13
     point_name = models.CharField(_('point_name'), max_length=255, blank=True, null=True, help_text='隔离点名称')
14
+
14 15
     # [{"start": "8:00", "end": "9:00"}, {"start": "12:00", "end": "14:00"}]
15 16
     point_measure_window = JSONField(_('point_measure_window'), default=[], blank=True, null=True, help_text='隔离点测温时间段')
16 17
 
18
+    # {
19
+    #     "type": "input",  # input, select, file
20
+    #     "name": "",
21
+    #     "options": ["男", "女"],  # type=select
22
+    # }
23
+    point_fields = JSONField(_('point_fields'), default=[], blank=True, null=True, help_text='字段列表')
24
+
25
+    limit_scene_qrcode_url = models.CharField(_('limit_scene_qrcode_url'), max_length=255, blank=True, null=True, help_text='字段二维码')
26
+
17 27
     class Meta:
18 28
         verbose_name = _('隔离点信息')
19 29
         verbose_name_plural = _('隔离点信息')
@@ -42,6 +52,33 @@ class IsolationPointInfo(BaseModelMixin):
42 52
         return ''
43 53
 
44 54
 
55
+class IsolationPointUserInfo(BaseModelMixin):
56
+    point_id = models.CharField(_('point_id'), max_length=32, blank=True, null=True, help_text='隔离点唯一标识', db_index=True)
57
+
58
+    user_id = models.CharField(_('user_id'), max_length=32, blank=True, null=True, help_text='用户唯一标识', db_index=True)
59
+
60
+    fields = JSONField(_('fields'), default=[], blank=True, null=True, help_text='字段信息')
61
+
62
+    class Meta:
63
+        verbose_name = _('隔离点用户录入信息')
64
+        verbose_name_plural = _('隔离点用户录入信息')
65
+
66
+        unique_together = (
67
+            ('point_id', 'user_id'),
68
+        )
69
+
70
+    def __unicode__(self):
71
+        return self.pk
72
+
73
+    @property
74
+    def data(self):
75
+        return {
76
+            'point_id': self.point_id,
77
+            'user_id': self.user_id,
78
+            'fields': self.fields,
79
+        }
80
+
81
+
45 82
 class ThermometerEquipmentInfo(BaseModelMixin):
46 83
     ONLINE = 1
47 84
     OFFLINE = 0
@@ -70,6 +107,8 @@ class ThermometerEquipmentInfo(BaseModelMixin):
70 107
     active_at = models.DateTimeField(_('active_at'), blank=True, null=True, help_text=_('激活时间'))
71 108
 
72 109
     # 用户基本信息
110
+    ipui_pk = models.IntegerField(_('ipui_pk'), default=0, help_text='隔离点用户录入PK')
111
+
73 112
     name = models.CharField(_('name'), max_length=255, blank=True, null=True, help_text='用户姓名')
74 113
     sex = models.IntegerField(_('sex'), choices=SexModelMixin.SEX_TUPLE, default=SexModelMixin.UNKNOWN, help_text='用户性别')
75 114
     birth_stamp = models.BigIntegerField(_('birth_stamp'), default=0, help_text='生日时间戳')

+ 2 - 0
requirements_pywe.txt

@@ -1,2 +1,4 @@
1
+pywe-miniapp==1.1.6
1 2
 pywe-oauth==1.1.1
2 3
 pywe-pay==1.0.14
4
+pywe-storage==1.0.1