@@ -10,9 +10,9 @@ from account.models import (LensmanIncomeExpensesInfo, LensmanInfo, LensmanLogin |
||
| 10 | 10 |
|
| 11 | 11 |
class LensmanInfoAdmin(admin.ModelAdmin): |
| 12 | 12 |
readonly_fields = ('lensman_id', 'encryption', )
|
| 13 |
- list_display = ('lensman_id', 'username', 'name', 'sex', 'phone', 'location', 'proportion', 'status', 'created_at', 'updated_at')
|
|
| 13 |
+ list_display = ('lensman_id', 'unionid', 'username', 'name', 'sex', 'phone', 'location', 'proportion', 'balance', 'user_status', 'status', 'created_at', 'updated_at')
|
|
| 14 | 14 |
search_fields = ('name', 'phone', 'location')
|
| 15 |
- list_filter = ('sex', 'status')
|
|
| 15 |
+ list_filter = ('sex', 'user_status', 'status')
|
|
| 16 | 16 |
|
| 17 | 17 |
def save_model(self, request, obj, form, change): |
| 18 | 18 |
if not obj.lensman_id: |
@@ -20,11 +20,12 @@ class LensmanInfoAdmin(admin.ModelAdmin): |
||
| 20 | 20 |
obj.lensman_id = user_id |
| 21 | 21 |
|
| 22 | 22 |
fields = {
|
| 23 |
+ 'unionid': obj.unionid, |
|
| 23 | 24 |
'name': obj.name, |
| 24 | 25 |
'sex': obj.sex, |
| 25 | 26 |
'phone': obj.phone, |
| 26 | 27 |
'location': obj.location, |
| 27 |
- 'user_status': obj.status, |
|
| 28 |
+ 'user_status': obj.user_status, |
|
| 28 | 29 |
} |
| 29 | 30 |
user, created = UserInfo.objects.get_or_create(user_id=obj.lensman_id, user_from=UserInfo.LENSMAN_USER, defaults=fields) |
| 30 | 31 |
if not created: |
@@ -49,7 +50,7 @@ class LensmanIncomeExpensesInfoAdmin(admin.ModelAdmin): |
||
| 49 | 50 |
|
| 50 | 51 |
class UserInfoAdmin(admin.ModelAdmin): |
| 51 | 52 |
readonly_fields = ('user_id', )
|
| 52 |
- list_display = ('user_id', 'user_from', 'username', 'wx_uid', 'name', 'sex', 'nickname', 'phone', 'location', 'balance', 'user_status', 'status', 'created_at', 'updated_at')
|
|
| 53 |
+ list_display = ('user_id', 'user_from', 'username', 'wx_uid', 'unionid', 'name', 'sex', 'nickname', 'phone', 'location', 'balance', 'user_status', 'status', 'created_at', 'updated_at')
|
|
| 53 | 54 |
search_fields = ('name', 'phone', 'location')
|
| 54 | 55 |
list_filter = ('user_from', 'sex', 'user_status', 'status')
|
| 55 | 56 |
|
@@ -0,0 +1,52 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+from __future__ import unicode_literals |
|
| 3 |
+ |
|
| 4 |
+from django.db import models, migrations |
|
| 5 |
+import jsonfield.fields |
|
| 6 |
+ |
|
| 7 |
+ |
|
| 8 |
+class Migration(migrations.Migration): |
|
| 9 |
+ |
|
| 10 |
+ dependencies = [ |
|
| 11 |
+ ('account', '0012_auto_20160627_1419'),
|
|
| 12 |
+ ] |
|
| 13 |
+ |
|
| 14 |
+ operations = [ |
|
| 15 |
+ migrations.CreateModel( |
|
| 16 |
+ name='WechatInfo', |
|
| 17 |
+ fields=[ |
|
| 18 |
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
|
| 19 |
+ ('status', models.BooleanField(default=True, help_text='\u72b6\u6001', db_index=True, verbose_name='status')),
|
|
| 20 |
+ ('created_at', models.DateTimeField(help_text='\u521b\u5efa\u65f6\u95f4', verbose_name='created_at', auto_now_add=True)),
|
|
| 21 |
+ ('updated_at', models.DateTimeField(help_text='\u66f4\u65b0\u65f6\u95f4', verbose_name='updated_at', auto_now=True)),
|
|
| 22 |
+ ('unionid', models.CharField(help_text='\u5fae\u4fe1 Union ID', max_length=255, null=True, verbose_name='unionid', blank=True)),
|
|
| 23 |
+ ('openids', jsonfield.fields.JSONField(help_text='\u5fae\u4fe1 Open IDs', null=True, verbose_name='openids', blank=True)),
|
|
| 24 |
+ ('sex', models.IntegerField(default=1, help_text='\u7528\u6237\u6027\u522b', verbose_name='sex', choices=[(1, '\u7537'), (0, '\u5973')])),
|
|
| 25 |
+ ('nickname', models.CharField(help_text='\u7528\u6237\u6635\u79f0', max_length=255, null=True, verbose_name='nickname', blank=True)),
|
|
| 26 |
+ ('headimgurl', models.CharField(help_text='\u7528\u6237\u5934\u50cf', max_length=255, null=True, verbose_name='headimgurl', blank=True)),
|
|
| 27 |
+ ('country', models.CharField(help_text='\u7528\u6237\u56fd\u5bb6', max_length=255, null=True, verbose_name='country', blank=True)),
|
|
| 28 |
+ ('province', models.CharField(help_text='\u7528\u6237\u7701\u4efd', max_length=255, null=True, verbose_name='province', blank=True)),
|
|
| 29 |
+ ('city', models.CharField(help_text='\u7528\u6237\u57ce\u5e02', max_length=255, null=True, verbose_name='city', blank=True)),
|
|
| 30 |
+ ('location', models.CharField(help_text='\u7528\u6237\u5730\u5740', max_length=255, null=True, verbose_name='location', blank=True)),
|
|
| 31 |
+ ], |
|
| 32 |
+ options={
|
|
| 33 |
+ 'verbose_name': 'wechatinfo', |
|
| 34 |
+ 'verbose_name_plural': 'wechatinfo', |
|
| 35 |
+ }, |
|
| 36 |
+ ), |
|
| 37 |
+ migrations.AddField( |
|
| 38 |
+ model_name='lensmaninfo', |
|
| 39 |
+ name='unionid', |
|
| 40 |
+ field=models.CharField(null=True, max_length=255, blank=True, help_text='\u5fae\u4fe1 Union ID', unique=True, verbose_name='unionid', db_index=True), |
|
| 41 |
+ ), |
|
| 42 |
+ migrations.AddField( |
|
| 43 |
+ model_name='lensmaninfo', |
|
| 44 |
+ name='user_status', |
|
| 45 |
+ field=models.IntegerField(default=0, verbose_name='user_status', choices=[(0, '\u672a\u9a8c\u8bc1'), (1, '\u5df2\u6fc0\u6d3b'), (2, '\u5df2\u7981\u7528'), (3, '\u5df2\u5220\u9664'), (10, '\u5df2\u5206\u914d')]), |
|
| 46 |
+ ), |
|
| 47 |
+ migrations.AlterField( |
|
| 48 |
+ model_name='userinfo', |
|
| 49 |
+ name='unionid', |
|
| 50 |
+ field=models.CharField(null=True, max_length=255, blank=True, help_text='\u5fae\u4fe1 Union ID', unique=True, verbose_name='unionid', db_index=True), |
|
| 51 |
+ ), |
|
| 52 |
+ ] |
@@ -2,6 +2,7 @@ |
||
| 2 | 2 |
|
| 3 | 3 |
from django.db import models |
| 4 | 4 |
from django.utils.translation import ugettext_lazy as _ |
| 5 |
+from jsonfield import JSONField |
|
| 5 | 6 |
|
| 6 | 7 |
from pai2.basemodels import CreateUpdateMixin |
| 7 | 8 |
|
@@ -15,8 +16,24 @@ class LensmanInfo(CreateUpdateMixin): |
||
| 15 | 16 |
(FEMALE, u'女'), |
| 16 | 17 |
) |
| 17 | 18 |
|
| 19 |
+ UNVERIFIED = 0 |
|
| 20 |
+ ACTIVATED = 1 |
|
| 21 |
+ DISABLED = 2 |
|
| 22 |
+ DELETED = 3 |
|
| 23 |
+ ASSIGN = 10 |
|
| 24 |
+ |
|
| 25 |
+ USER_STATUS = ( |
|
| 26 |
+ (UNVERIFIED, u'未验证'), |
|
| 27 |
+ (ACTIVATED, u'已激活'), |
|
| 28 |
+ (DISABLED, u'已禁用'), |
|
| 29 |
+ (DELETED, u'已删除'), |
|
| 30 |
+ (ASSIGN, u'已分配'), |
|
| 31 |
+ ) |
|
| 32 |
+ |
|
| 18 | 33 |
lensman_id = models.CharField(_(u'lensman_id'), max_length=255, blank=True, null=True, help_text=u'摄影师唯一标识', db_index=True, unique=True) |
| 19 | 34 |
|
| 35 |
+ unionid = models.CharField(_(u'unionid'), max_length=255, blank=True, null=True, help_text=u'微信 Union ID', db_index=True, unique=True) |
|
| 36 |
+ |
|
| 20 | 37 |
username = models.CharField(_(u'username'), max_length=255, blank=True, null=True, help_text=u'摄影师用户名', db_index=True, unique=True) |
| 21 | 38 |
password = models.CharField(_(u'password'), max_length=255, blank=True, null=True, help_text=u'摄影师密码') |
| 22 | 39 |
encryption = models.CharField(_(u'encryption'), max_length=255, blank=True, null=True, help_text=u'摄影师密码') |
@@ -30,6 +47,8 @@ class LensmanInfo(CreateUpdateMixin): |
||
| 30 | 47 |
|
| 31 | 48 |
balance = models.IntegerField(_(u'balance'), default=0, help_text=u'摄影师余额(分)') |
| 32 | 49 |
|
| 50 |
+ user_status = models.IntegerField(_(u'user_status'), choices=USER_STATUS, default=UNVERIFIED) |
|
| 51 |
+ |
|
| 33 | 52 |
signup_ip = models.CharField(_(u'signup_ip'), max_length=255, blank=True, null=True, help_text=_(u'注册IP')) |
| 34 | 53 |
login_ip = models.CharField(_(u'login_ip'), max_length=255, blank=True, null=True, help_text=_(u'登录IP')) |
| 35 | 54 |
login_at = models.DateTimeField(_(u'login_at'), blank=True, null=True, help_text=_(u'登录时间')) |
@@ -41,6 +60,15 @@ class LensmanInfo(CreateUpdateMixin): |
||
| 41 | 60 |
def __unicode__(self): |
| 42 | 61 |
return unicode(self.pk) |
| 43 | 62 |
|
| 63 |
+ @property |
|
| 64 |
+ def data(self): |
|
| 65 |
+ return {
|
|
| 66 |
+ 'name': self.name, |
|
| 67 |
+ 'sex': self.sex, |
|
| 68 |
+ 'phone': self.phone, |
|
| 69 |
+ 'location': self.location, |
|
| 70 |
+ } |
|
| 71 |
+ |
|
| 44 | 72 |
|
| 45 | 73 |
class LensmanLoginLogInfo(CreateUpdateMixin): |
| 46 | 74 |
SUCCESS = 0 |
@@ -91,6 +119,33 @@ class LensmanIncomeExpensesInfo(CreateUpdateMixin): |
||
| 91 | 119 |
return unicode(self.pk) |
| 92 | 120 |
|
| 93 | 121 |
|
| 122 |
+class WechatInfo(CreateUpdateMixin): |
|
| 123 |
+ MALE = 1 |
|
| 124 |
+ FEMALE = 0 |
|
| 125 |
+ |
|
| 126 |
+ SEX_TYPE = ( |
|
| 127 |
+ (MALE, u'男'), |
|
| 128 |
+ (FEMALE, u'女'), |
|
| 129 |
+ ) |
|
| 130 |
+ |
|
| 131 |
+ unionid = models.CharField(_(u'unionid'), max_length=255, blank=True, null=True, help_text=u'微信 Union ID') |
|
| 132 |
+ openids = JSONField(_(u'openids'), blank=True, null=True, help_text=u'微信 Open IDs') |
|
| 133 |
+ sex = models.IntegerField(_(u'sex'), choices=SEX_TYPE, default=MALE, help_text=u'用户性别') |
|
| 134 |
+ nickname = models.CharField(_(u'nickname'), max_length=255, blank=True, null=True, help_text=u'用户昵称') |
|
| 135 |
+ headimgurl = models.CharField(_(u'headimgurl'), max_length=255, blank=True, null=True, help_text=u'用户头像') |
|
| 136 |
+ country = models.CharField(_(u'country'), max_length=255, blank=True, null=True, help_text=u'用户国家') |
|
| 137 |
+ province = models.CharField(_(u'province'), max_length=255, blank=True, null=True, help_text=u'用户省份') |
|
| 138 |
+ city = models.CharField(_(u'city'), max_length=255, blank=True, null=True, help_text=u'用户城市') |
|
| 139 |
+ location = models.CharField(_(u'location'), max_length=255, blank=True, null=True, help_text=u'用户地址') |
|
| 140 |
+ |
|
| 141 |
+ class Meta: |
|
| 142 |
+ verbose_name = _(u'wechatinfo') |
|
| 143 |
+ verbose_name_plural = _(u'wechatinfo') |
|
| 144 |
+ |
|
| 145 |
+ def __unicode__(self): |
|
| 146 |
+ return unicode(self.pk) |
|
| 147 |
+ |
|
| 148 |
+ |
|
| 94 | 149 |
class UserInfo(CreateUpdateMixin): |
| 95 | 150 |
APP_USER = 0 |
| 96 | 151 |
WX_USER = 1 |
@@ -135,8 +190,7 @@ class UserInfo(CreateUpdateMixin): |
||
| 135 | 190 |
password = models.CharField(_(u'password'), max_length=255, blank=True, null=True, help_text=u'用户密码') |
| 136 | 191 |
# 微信授权用户 |
| 137 | 192 |
wx_uid = models.CharField(_(u'wx_uid'), max_length=255, blank=True, null=True, help_text=u'微信唯一标识', db_index=True, unique=True) |
| 138 |
- unionid = models.CharField(_(u'unionid'), max_length=255, blank=True, null=True, help_text=u'微信 Union ID') |
|
| 139 |
- # openid = models.CharField(_(u'openid'), max_length=255, blank=True, null=True, help_text=u'微信 Open ID') |
|
| 193 |
+ unionid = models.CharField(_(u'unionid'), max_length=255, blank=True, null=True, help_text=u'微信 Union ID', db_index=True, unique=True) |
|
| 140 | 194 |
# 用户基本信息 |
| 141 | 195 |
name = models.CharField(_(u'name'), max_length=255, blank=True, null=True, help_text=u'用户姓名') |
| 142 | 196 |
sex = models.IntegerField(_(u'sex'), choices=SEX_TYPE, default=MALE, help_text=u'用户性别') |
@@ -130,8 +130,8 @@ def user_login_api(request): |
||
| 130 | 130 |
|
| 131 | 131 |
def wx_authorize_api(request): |
| 132 | 132 |
user_id = request.POST.get('user_id', '')
|
| 133 |
- wx_uid = request.POST.get('wx_uid', '')
|
|
| 134 | 133 |
|
| 134 |
+ openid = wx_uid = request.POST.get('wx_uid', '')
|
|
| 135 | 135 |
unionid = request.POST.get('unionid', '')
|
| 136 | 136 |
|
| 137 | 137 |
sex = request.POST.get('sex', 0)
|
@@ -141,9 +141,9 @@ def wx_authorize_api(request): |
||
| 141 | 141 |
province = request.POST.get('province', '')
|
| 142 | 142 |
city = request.POST.get('city', '')
|
| 143 | 143 |
|
| 144 |
- # 判断 wx_uid 是否已经存在,如果已经存在,则直接返回改帐户信息 |
|
| 144 |
+ # 判断 unionid 是否已经存在,如果已经存在,则直接返回改帐户信息 |
|
| 145 | 145 |
try: |
| 146 |
- user = UserInfo.objects.get(wx_uid=wx_uid) |
|
| 146 |
+ user = UserInfo.objects.get(unionid=unionid) |
|
| 147 | 147 |
except UserInfo.DoesNotExist: |
| 148 | 148 |
user = None |
| 149 | 149 |
|
@@ -163,7 +163,7 @@ def wx_authorize_api(request): |
||
| 163 | 163 |
'data': user.data, |
| 164 | 164 |
}) |
| 165 | 165 |
|
| 166 |
- # wx_uid 不存在 |
|
| 166 |
+ # unionid 不存在 |
|
| 167 | 167 |
# 判断 user_id 是否存在并且为分配用户,如果存在并且为分配用户,则直接在该帐户上更新,否则则直接创建帐户 |
| 168 | 168 |
|
| 169 | 169 |
signup_ip, signup_at = ip_addr(request), tc.utc_datetime() |
@@ -27,6 +27,7 @@ urlpatterns = [ |
||
| 27 | 27 |
|
| 28 | 28 |
# 摄影师相关 |
| 29 | 29 |
urlpatterns += [ |
| 30 |
+ url(r'^l/submit$', lensman_views.lensman_submit_api, name='lensman_submit_api'), # 摄影师登录 |
|
| 30 | 31 |
url(r'^l/login$', lensman_views.lensman_login_api, name='lensman_login_api'), # 摄影师登录 |
| 31 | 32 |
url(r'^l/photos/upload$', lensman_views.lensman_upload_photo_api, name='lensman_upload_photo_api'), # 摄影师上传照片 |
| 32 | 33 |
] |
@@ -104,7 +105,13 @@ urlpatterns += [ |
||
| 104 | 105 |
url(r'^wx/balance_withdraw$', pay_views.wx_balance_withdraw_api, name='wx_balance_withdraw_api'), # 余额提现: 企业付款/现金红包 |
| 105 | 106 |
] |
| 106 | 107 |
|
| 107 |
-# 分享相关 |
|
| 108 |
+# 微信授权相关 |
|
| 109 |
+urlpatterns += [ |
|
| 110 |
+ url(r'^get_openid$', wechat_views.get_openid, name='get_openid'), |
|
| 111 |
+ url(r'^to_redirect$', wechat_views.to_redirect, name='to_redirect'), |
|
| 112 |
+] |
|
| 113 |
+ |
|
| 114 |
+# 微信分享相关 |
|
| 108 | 115 |
urlpatterns += [ |
| 109 | 116 |
url(r'^wx/jsapi_signature$', wechat_views.wx_jsapi_signature_api, name='wx_jsapi_signature_api'), # jsapi_signature |
| 110 | 117 |
] |
@@ -26,6 +26,35 @@ from utils.watermark_utils import watermark_wrap |
||
| 26 | 26 |
r = settings.REDIS_CACHE |
| 27 | 27 |
|
| 28 | 28 |
|
| 29 |
+def lensman_submit_api(request): |
|
| 30 |
+ """ |
|
| 31 |
+ 摄影师信息提交 |
|
| 32 |
+ :param request: |
|
| 33 |
+ :return: |
|
| 34 |
+ """ |
|
| 35 |
+ unionid = request.POST.get('unionid', '')
|
|
| 36 |
+ phone = request.POST.get('phone', '')
|
|
| 37 |
+ |
|
| 38 |
+ if LensmanInfo.objects.filter(phone=phone).exclude(unionid=unionid).exists(): |
|
| 39 |
+ return response(LensmanStatusCode.LENSMAN_PHONE_ALREADY_EXISTS) |
|
| 40 |
+ |
|
| 41 |
+ fields = {
|
|
| 42 |
+ 'name': request.POST.get('name', ''),
|
|
| 43 |
+ 'sex': int(request.POST.get('sex', 1)),
|
|
| 44 |
+ 'phone': phone, |
|
| 45 |
+ 'location': request.POST.get('location', ''),
|
|
| 46 |
+ 'user_status': LensmanInfo.UNVERIFIED, |
|
| 47 |
+ } |
|
| 48 |
+ |
|
| 49 |
+ lensman, created = LensmanInfo.objects.get_or_create(unionid=unionid, defaults=fields) |
|
| 50 |
+ if not created: |
|
| 51 |
+ for key, value in fields.iteritems(): |
|
| 52 |
+ setattr(lensman, key, value) |
|
| 53 |
+ lensman.save() |
|
| 54 |
+ |
|
| 55 |
+ return response(200, 'Submit Success', u'提交成功', {})
|
|
| 56 |
+ |
|
| 57 |
+ |
|
| 29 | 58 |
def lensman_login_api(request): |
| 30 | 59 |
""" |
| 31 | 60 |
摄影师登录 |
@@ -0,0 +1,154 @@ |
||
| 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="https://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: rgba(0, 0, 0); |
|
| 20 |
+ } |
|
| 21 |
+ |
|
| 22 |
+ </style> |
|
| 23 |
+</head> |
|
| 24 |
+<body> |
|
| 25 |
+ <div class="container" > |
|
| 26 |
+ <div class="weui_cells weui_cells_form"> |
|
| 27 |
+ <div class="weui_cell"> |
|
| 28 |
+ <div class="weui_cell_hd"><label for="" class="weui_label">姓名</label></div> |
|
| 29 |
+ <div class="weui_cell_bd weui_cell_primary"> |
|
| 30 |
+ <input id="name" class="weui_input" type="text" value="{{ lensman_info.name }}" placeholder="请输入姓名">
|
|
| 31 |
+ </div> |
|
| 32 |
+ </div> |
|
| 33 |
+ <div class="weui_cell weui_cell_select weui_select_after"> |
|
| 34 |
+ <div class="weui_cell_hd"><label for="" class="weui_label">性别</label></div> |
|
| 35 |
+ <div class="weui_cell_bd weui_cell_primary"> |
|
| 36 |
+ <select id="sex" class="weui_select" name="select"> |
|
| 37 |
+ <option value="1" {% ifequal lensman_info.sex 1 %}selected{% endifequal %}>男</option>
|
|
| 38 |
+ <option value="0" {% ifequal lensman_info.sex 0 %}selected{% endifequal %}>女</option>
|
|
| 39 |
+ </select> |
|
| 40 |
+ </div> |
|
| 41 |
+ </div> |
|
| 42 |
+ <div class="weui_cell"> |
|
| 43 |
+ <div class="weui_cell_hd"><label for="" class="weui_label">手机号</label></div> |
|
| 44 |
+ <div class="weui_cell_bd weui_cell_primary"> |
|
| 45 |
+ <input id="phone" class="weui_input" type="text" required="required" pattern="[0-9]{11}" value="{{ lensman_info.phone }}" placeholder="请输入手机号">
|
|
| 46 |
+ </div> |
|
| 47 |
+ </div> |
|
| 48 |
+ <div class="weui_cell"> |
|
| 49 |
+ <div class="weui_cell_hd"><label for="" class="weui_label">地址</label></div> |
|
| 50 |
+ <div class="weui_cell_bd weui_cell_primary"> |
|
| 51 |
+ <input id="location" class="weui_input" type="text" value="{{ lensman_info.location }}" placeholder="请输入地址">
|
|
| 52 |
+ </div> |
|
| 53 |
+ </div> |
|
| 54 |
+ </div> |
|
| 55 |
+ |
|
| 56 |
+ <br> |
|
| 57 |
+ |
|
| 58 |
+ <button id="submit" class="weui_btn weui_btn_warn">确认</button> |
|
| 59 |
+ |
|
| 60 |
+ <div class="weui_dialog_alert" id="dialog" style="display: none"> |
|
| 61 |
+ <div class="weui_mask"></div> |
|
| 62 |
+ <div class="weui_dialog"> |
|
| 63 |
+ <div class="weui_dialog_hd"><strong id="title" class="weui_dialog_title">弹窗标题</strong></div> |
|
| 64 |
+ <div id="content" class="weui_dialog_bd">弹窗内容,告知当前页面信息等</div> |
|
| 65 |
+ <div class="weui_dialog_ft"> |
|
| 66 |
+ <a href="javascript:;" class="weui_btn_dialog primary">确定</a> |
|
| 67 |
+ </div> |
|
| 68 |
+ </div> |
|
| 69 |
+ </div> |
|
| 70 |
+ |
|
| 71 |
+ <div id="toast" style="display: none;"> |
|
| 72 |
+ <div class="weui_mask_transparent"></div> |
|
| 73 |
+ <div class="weui_toast"> |
|
| 74 |
+ <i class="weui_icon_toast"></i> |
|
| 75 |
+ <p class="weui_toast_content">已完成</p> |
|
| 76 |
+ </div> |
|
| 77 |
+ </div> |
|
| 78 |
+ </div> |
|
| 79 |
+ |
|
| 80 |
+ <script src="//cdn.bootcss.com/zepto/1.1.6/zepto.min.js"></script> |
|
| 81 |
+ <script> |
|
| 82 |
+ $(function() {
|
|
| 83 |
+ function getURLParameter(name) {
|
|
| 84 |
+ return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search) || [null, ''])[1].replace(/\+/g, '%20')) || null;
|
|
| 85 |
+ } |
|
| 86 |
+ |
|
| 87 |
+ function show_error_dialog(title, content) {
|
|
| 88 |
+ $('#dialog #title').text(title);
|
|
| 89 |
+ $('#dialog #content').text(content);
|
|
| 90 |
+ $('#dialog').show();
|
|
| 91 |
+ } |
|
| 92 |
+ |
|
| 93 |
+ function data_check() {
|
|
| 94 |
+ var unionid = getURLParameter('unionid');
|
|
| 95 |
+ if (!unionid) {
|
|
| 96 |
+ show_error_dialog('微信授权', '微信授权失败,请重新打开页面');
|
|
| 97 |
+ return false; |
|
| 98 |
+ } |
|
| 99 |
+ |
|
| 100 |
+ var name = $('#name').val();
|
|
| 101 |
+ if (!name) {
|
|
| 102 |
+ show_error_dialog('姓名', '姓名错误,请检查重新输入');
|
|
| 103 |
+ return false; |
|
| 104 |
+ } |
|
| 105 |
+ |
|
| 106 |
+ var phone_valid = $('#phone').is(':valid');
|
|
| 107 |
+ if (!phone_valid) {
|
|
| 108 |
+ show_error_dialog('手机号', '手机号错误,请检查重新输入');
|
|
| 109 |
+ return false; |
|
| 110 |
+ } |
|
| 111 |
+ |
|
| 112 |
+ var location = $('#location').val();
|
|
| 113 |
+ if (!location) {
|
|
| 114 |
+ show_error_dialog('地址', '地址错误,请检查重新输入');
|
|
| 115 |
+ return false; |
|
| 116 |
+ } |
|
| 117 |
+ |
|
| 118 |
+ return {
|
|
| 119 |
+ unionid: unionid, |
|
| 120 |
+ name: name, |
|
| 121 |
+ sex: $('#sex option:checked').val(),
|
|
| 122 |
+ phone: $('#phone').val(),
|
|
| 123 |
+ location: location, |
|
| 124 |
+ } |
|
| 125 |
+ } |
|
| 126 |
+ |
|
| 127 |
+ $('#submit').click(function () {
|
|
| 128 |
+ var check_result = data_check(); |
|
| 129 |
+ if (check_result){
|
|
| 130 |
+ $.ajax({
|
|
| 131 |
+ type: 'POST', |
|
| 132 |
+ url: 'l/submit', |
|
| 133 |
+ data: check_result, |
|
| 134 |
+ success: function(data) {
|
|
| 135 |
+ if (data.status == 200) {
|
|
| 136 |
+ $('#toast').show();
|
|
| 137 |
+ setTimeout(function () {
|
|
| 138 |
+ $('#toast').hide();
|
|
| 139 |
+ }, 1000); |
|
| 140 |
+ } else {
|
|
| 141 |
+ show_error_dialog('错误', data.description);
|
|
| 142 |
+ } |
|
| 143 |
+ } |
|
| 144 |
+ }) |
|
| 145 |
+ } |
|
| 146 |
+ }); |
|
| 147 |
+ |
|
| 148 |
+ $('#dialog .weui_btn_dialog').click(function () {
|
|
| 149 |
+ $('#dialog').hide();
|
|
| 150 |
+ }) |
|
| 151 |
+ }); |
|
| 152 |
+ </script> |
|
| 153 |
+</body> |
|
| 154 |
+</html> |
@@ -2,6 +2,8 @@ |
||
| 2 | 2 |
|
| 3 | 3 |
from django.shortcuts import render |
| 4 | 4 |
|
| 5 |
+from account.models import LensmanInfo |
|
| 6 |
+ |
|
| 5 | 7 |
|
| 6 | 8 |
def user_agreement(request): |
| 7 | 9 |
return render(request, 'page/user_agreement.html', {})
|
@@ -9,3 +11,16 @@ def user_agreement(request): |
||
| 9 | 11 |
|
| 10 | 12 |
def contact_us(request): |
| 11 | 13 |
return render(request, 'page/contact_us.html', {})
|
| 14 |
+ |
|
| 15 |
+ |
|
| 16 |
+def lensman_oauth(request): |
|
| 17 |
+ unionid = request.GET.get('unionid', '')
|
|
| 18 |
+ |
|
| 19 |
+ try: |
|
| 20 |
+ lensman = LensmanInfo.objects.get(unionid=unionid) |
|
| 21 |
+ except LensmanInfo.DoesNotExist: |
|
| 22 |
+ lensman = None |
|
| 23 |
+ |
|
| 24 |
+ return render(request, 'page/lensman_oauth.html', {
|
|
| 25 |
+ 'lensman_info': lensman and lensman.data |
|
| 26 |
+ }) |
@@ -23,6 +23,7 @@ from rest_framework import routers |
||
| 23 | 23 |
|
| 24 | 24 |
from account import views as account_views |
| 25 | 25 |
from group import views as group_views |
| 26 |
+from group import lensman_views |
|
| 26 | 27 |
from page import views as page_views |
| 27 | 28 |
from photo import views as photo_views |
| 28 | 29 |
from website import views as website_views |
@@ -65,6 +66,8 @@ urlpatterns += [ |
||
| 65 | 66 |
urlpatterns += [ |
| 66 | 67 |
url(r'^page/user_agreement$', page_views.user_agreement, name='user_agreement'), # 用户协议页面 |
| 67 | 68 |
url(r'^page/contact_us$', page_views.contact_us, name='contact_us'), # 联系我们页面 |
| 69 |
+ |
|
| 70 |
+ url(r'^page/lensman$', page_views.lensman_oauth, name='lensman_oauth'), # 摄影师授权页面 |
|
| 68 | 71 |
] |
| 69 | 72 |
|
| 70 | 73 |
urlpatterns += [ |
@@ -75,6 +78,11 @@ urlpatterns += [ |
||
| 75 | 78 |
url(r'^termofservice$', website_views.pai2_termofservice, name='pai2_termofservice'), # 官网服务条款 |
| 76 | 79 |
] |
| 77 | 80 |
|
| 81 |
+# 摄影师相关 |
|
| 82 |
+urlpatterns += [ |
|
| 83 |
+ url(r'^page/l/submit$', lensman_views.lensman_submit_api, name='lensman_submit_api'), # 摄影师登录 |
|
| 84 |
+] |
|
| 85 |
+ |
|
| 78 | 86 |
# Wire up our API using automatic URL routing. |
| 79 | 87 |
# Additionally, we include login URLs for the browsable API. |
| 80 | 88 |
urlpatterns += [ |
@@ -11,12 +11,14 @@ django-logit==1.0.2 |
||
| 11 | 11 |
django-multidomain==1.1.4 |
| 12 | 12 |
django-shortuuidfield==0.1.3 |
| 13 | 13 |
djangorestframework==3.3.1 |
| 14 |
+furl==0.4.95 |
|
| 14 | 15 |
hiredis==0.2.0 |
| 15 | 16 |
ipdb==0.8.1 |
| 16 | 17 |
ipython==4.0.0 |
| 17 | 18 |
jsonfield==1.0.3 |
| 18 | 19 |
kkconst==1.1.2 |
| 19 | 20 |
pep8==1.6.2 |
| 21 |
+pysnippets==1.0.2 |
|
| 20 | 22 |
pytz==2015.7 |
| 21 | 23 |
records==0.4.3 |
| 22 | 24 |
redis==2.10.5 |
@@ -19,6 +19,8 @@ class LensmanStatusCode(BaseStatusCode): |
||
| 19 | 19 |
LENSMAN_NOT_FOUND = StatusCodeField(400001, u'Lensman Not Found', description=u'摄影师不存在') |
| 20 | 20 |
LENSMAN_PASSWORD_ERROR = StatusCodeField(400002, u'Lensman Password Error', description=u'摄影师密码错误') |
| 21 | 21 |
|
| 22 |
+ LENSMAN_PHONE_ALREADY_EXISTS = StatusCodeField(400005, u'Lensman Phone Already Exists', description=u'手机号已经存在') |
|
| 23 |
+ |
|
| 22 | 24 |
|
| 23 | 25 |
class UserStatusCode(BaseStatusCode): |
| 24 | 26 |
""" 用户相关错误码 4001xx """ |
@@ -1,10 +1,16 @@ |
||
| 1 | 1 |
# -*- coding: utf-8 -*- |
| 2 | 2 |
|
| 3 | 3 |
import time |
| 4 |
+import urllib |
|
| 4 | 5 |
|
| 6 |
+import requests |
|
| 5 | 7 |
import shortuuid |
| 8 |
+from CodeConvert import CodeConvert as cc |
|
| 6 | 9 |
from django.conf import settings |
| 10 |
+from django.shortcuts import redirect |
|
| 11 |
+from furl import furl |
|
| 7 | 12 |
from json_response import auto_response |
| 13 |
+from pysnippets import dictsnippets as dsnippets |
|
| 8 | 14 |
from wechatpy import WeChatClient |
| 9 | 15 |
|
| 10 | 16 |
|
@@ -13,6 +19,33 @@ WECHAT = settings.WECHAT |
||
| 13 | 19 |
JSAPI = WECHAT.get('JSAPI', {})
|
| 14 | 20 |
|
| 15 | 21 |
|
| 22 |
+def get_openid(request): |
|
| 23 |
+ scope = request.GET.get('scope', 'snsapi_userinfo')
|
|
| 24 |
+ redirect_url = request.GET.get('redirect_url', '')
|
|
| 25 |
+ default_url = request.GET.get('default_url', '')
|
|
| 26 |
+ |
|
| 27 |
+ if request.weixin: |
|
| 28 |
+ authorize_url = settings.WECHAT_GET_CODE_USERINFO if scope == 'snsapi_userinfo' else settings.WECHAT_GET_CODE_BASE |
|
| 29 |
+ get_code_url = authorize_url % (JSAPI['appID'], urllib.quote_plus(settings.WECHAT_REDIRECT_URI), urllib.quote_plus(redirect_url)) |
|
| 30 |
+ return redirect(get_code_url) |
|
| 31 |
+ |
|
| 32 |
+ return redirect(default_url if default_url else redirect_url) |
|
| 33 |
+ |
|
| 34 |
+ |
|
| 35 |
+def to_redirect(request): |
|
| 36 |
+ code = request.GET.get('code', '')
|
|
| 37 |
+ state = request.GET.get('state', '')
|
|
| 38 |
+ |
|
| 39 |
+ access_info = requests.get(settings.WECHAT_GET_OAUTH2_ACCESS_TOKEN % (JSAPI['appID'], JSAPI['appsecret'], code), verify=False).json() |
|
| 40 |
+ unionid, openid, access_token = access_info.get('unionid', ''), access_info.get('openid', ''), access_info.get('access_token', '')
|
|
| 41 |
+ |
|
| 42 |
+ res = requests.get(settings.WECHAT_GET_USERINFO % (access_token, openid), verify=False) |
|
| 43 |
+ res.encoding = 'utf-8' |
|
| 44 |
+ userinfo = res.json() |
|
| 45 |
+ |
|
| 46 |
+ return redirect(furl(state).add(cc.Convert2Utf8(dsnippets.filter(userinfo, ['unionid', 'openid', 'nickname', 'headimgurl']))).url) |
|
| 47 |
+ |
|
| 48 |
+ |
|
| 16 | 49 |
@auto_response |
| 17 | 50 |
def wx_jsapi_signature_api(request): |
| 18 | 51 |
url = request.GET.get('url', '')
|