@@ -5,8 +5,8 @@ from django.contrib import admin |
||
| 5 | 5 |
from django.contrib.auth.hashers import make_password |
| 6 | 6 |
from django.db import transaction |
| 7 | 7 |
|
| 8 |
-from account.models import (LensmanIncomeExpensesInfo, LensmanInfo, LensmanLoginLogInfo, UserIncomeExpensesInfo, |
|
| 9 |
- UserInfo, UserLoginLogInfo) |
|
| 8 |
+from account.models import (LensmanIncomeExpensesInfo, LensmanInfo, LensmanLoginLogInfo, TourGuideInfo, |
|
| 9 |
+ UserIncomeExpensesInfo, UserInfo, UserLoginLogInfo) |
|
| 10 | 10 |
|
| 11 | 11 |
|
| 12 | 12 |
class LensmanInfoAdmin(admin.ModelAdmin): |
@@ -31,10 +31,12 @@ class LensmanInfoAdmin(admin.ModelAdmin): |
||
| 31 | 31 |
'sex': obj.sex, |
| 32 | 32 |
'phone': obj.phone, |
| 33 | 33 |
'location': obj.location, |
| 34 |
+ 'islensman': True, |
|
| 34 | 35 |
'user_status': obj.user_status, |
| 35 | 36 |
} |
| 36 | 37 |
user, created = UserInfo.objects.get_or_create(user_id=obj.lensman_id, defaults=fields) |
| 37 | 38 |
if not created: |
| 39 |
+ fields.pop('user_from', None)
|
|
| 38 | 40 |
for key, value in fields.iteritems(): |
| 39 | 41 |
setattr(user, key, value) |
| 40 | 42 |
user.save() |
@@ -54,6 +56,40 @@ class LensmanIncomeExpensesInfoAdmin(admin.ModelAdmin): |
||
| 54 | 56 |
list_filter = ('type', 'status')
|
| 55 | 57 |
|
| 56 | 58 |
|
| 59 |
+class TourGuideInfoAdmin(admin.ModelAdmin): |
|
| 60 |
+ readonly_fields = ('tourguide_id', )
|
|
| 61 |
+ list_display = ('tourguide_id', 'unionid', 'name', 'sex', 'phone', 'location', 'no', 'user_status', 'status', 'created_at', 'updated_at')
|
|
| 62 |
+ search_fields = ('name', 'phone', 'location', 'no')
|
|
| 63 |
+ list_filter = ('sex', 'user_status', 'status')
|
|
| 64 |
+ |
|
| 65 |
+ @transaction.atomic |
|
| 66 |
+ def save_model(self, request, obj, form, change): |
|
| 67 |
+ if not obj.tourguide_id: |
|
| 68 |
+ try: |
|
| 69 |
+ user_id = UserInfo.objects.select_for_update().get(unionid=obj.unionid).user_id |
|
| 70 |
+ except UserInfo.DoesNotExist: |
|
| 71 |
+ user_id = None |
|
| 72 |
+ obj.tourguide_id = user_id or CurtailUUID.uuid(UserInfo, 'user_id') |
|
| 73 |
+ obj.save() |
|
| 74 |
+ |
|
| 75 |
+ fields = {
|
|
| 76 |
+ 'user_from': UserInfo.TOURGUIDE_USER, |
|
| 77 |
+ 'unionid': obj.unionid, |
|
| 78 |
+ 'name': obj.name, |
|
| 79 |
+ 'sex': obj.sex, |
|
| 80 |
+ 'phone': obj.phone, |
|
| 81 |
+ 'location': obj.location, |
|
| 82 |
+ 'istourguide': True, |
|
| 83 |
+ 'user_status': obj.user_status, |
|
| 84 |
+ } |
|
| 85 |
+ user, created = UserInfo.objects.get_or_create(user_id=obj.tourguide_id, defaults=fields) |
|
| 86 |
+ if not created: |
|
| 87 |
+ fields.pop('user_from', None)
|
|
| 88 |
+ for key, value in fields.iteritems(): |
|
| 89 |
+ setattr(user, key, value) |
|
| 90 |
+ user.save() |
|
| 91 |
+ |
|
| 92 |
+ |
|
| 57 | 93 |
class UserInfoAdmin(admin.ModelAdmin): |
| 58 | 94 |
readonly_fields = ('user_id', )
|
| 59 | 95 |
list_display = ('user_id', 'user_from', 'username', 'openid', 'unionid', 'name', 'sex', 'nickname', 'phone', 'location', 'balance', 'user_status', 'status', 'created_at', 'updated_at')
|
@@ -73,6 +109,7 @@ class UserIncomeExpensesInfoAdmin(admin.ModelAdmin): |
||
| 73 | 109 |
admin.site.register(LensmanInfo, LensmanInfoAdmin) |
| 74 | 110 |
admin.site.register(LensmanLoginLogInfo, LensmanLoginLogInfoAdmin) |
| 75 | 111 |
admin.site.register(LensmanIncomeExpensesInfo, LensmanIncomeExpensesInfoAdmin) |
| 112 |
+admin.site.register(TourGuideInfo, TourGuideInfoAdmin) |
|
| 76 | 113 |
admin.site.register(UserInfo, UserInfoAdmin) |
| 77 | 114 |
admin.site.register(UserLoginLogInfo, UserLoginLogInfoAdmin) |
| 78 | 115 |
admin.site.register(UserIncomeExpensesInfo, UserIncomeExpensesInfoAdmin) |
@@ -0,0 +1,36 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+from __future__ import unicode_literals |
|
| 3 |
+ |
|
| 4 |
+from django.db import models, migrations |
|
| 5 |
+ |
|
| 6 |
+ |
|
| 7 |
+class Migration(migrations.Migration): |
|
| 8 |
+ |
|
| 9 |
+ dependencies = [ |
|
| 10 |
+ ('account', '0019_auto_20161024_1235'),
|
|
| 11 |
+ ] |
|
| 12 |
+ |
|
| 13 |
+ operations = [ |
|
| 14 |
+ migrations.CreateModel( |
|
| 15 |
+ name='TourGuideInfo', |
|
| 16 |
+ fields=[ |
|
| 17 |
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
|
| 18 |
+ ('status', models.BooleanField(default=True, help_text='\u72b6\u6001', db_index=True, verbose_name='status')),
|
|
| 19 |
+ ('created_at', models.DateTimeField(help_text='\u521b\u5efa\u65f6\u95f4', verbose_name='created_at', auto_now_add=True)),
|
|
| 20 |
+ ('updated_at', models.DateTimeField(help_text='\u66f4\u65b0\u65f6\u95f4', verbose_name='updated_at', auto_now=True)),
|
|
| 21 |
+ ('tourguide_id', models.CharField(null=True, max_length=255, blank=True, help_text='\u5bfc\u6e38\u552f\u4e00\u6807\u8bc6', unique=True, verbose_name='tourguide_id', db_index=True)),
|
|
| 22 |
+ ('unionid', models.CharField(null=True, max_length=255, blank=True, help_text='\u5fae\u4fe1 Union ID', unique=True, verbose_name='unionid', db_index=True)),
|
|
| 23 |
+ ('name', models.CharField(help_text='\u5bfc\u6e38\u59d3\u540d', max_length=255, null=True, verbose_name='name', blank=True)),
|
|
| 24 |
+ ('sex', models.IntegerField(default=1, help_text='\u5bfc\u6e38\u6027\u522b', verbose_name='sex', choices=[(1, '\u7537'), (0, '\u5973')])),
|
|
| 25 |
+ ('phone', models.CharField(null=True, max_length=255, blank=True, help_text='\u5bfc\u6e38\u7535\u8bdd', unique=True, verbose_name='phone', db_index=True)),
|
|
| 26 |
+ ('location', models.CharField(help_text='\u5bfc\u6e38\u5730\u5740', max_length=255, null=True, verbose_name='location', blank=True)),
|
|
| 27 |
+ ('no', models.CharField(help_text='\u5bfc\u6e38\u8bc1\u7f16\u53f7', max_length=255, null=True, verbose_name='no', blank=True)),
|
|
| 28 |
+ ('user_status', models.IntegerField(default=0, verbose_name='user_status', choices=[(-1, '\u5df2\u62d2\u7edd'), (0, '\u672a\u9a8c\u8bc1'), (1, '\u5df2\u6fc0\u6d3b'), (2, '\u5df2\u7981\u7528'), (3, '\u5df2\u5220\u9664'), (10, '\u5df2\u5206\u914d')])),
|
|
| 29 |
+ ('refused_reason', models.TextField(help_text='\u5ba1\u6838\u62d2\u7edd\u539f\u56e0', null=True, verbose_name='refused_reason', blank=True)),
|
|
| 30 |
+ ], |
|
| 31 |
+ options={
|
|
| 32 |
+ 'verbose_name': 'tourguideinfo', |
|
| 33 |
+ 'verbose_name_plural': 'tourguideinfo', |
|
| 34 |
+ }, |
|
| 35 |
+ ), |
|
| 36 |
+ ] |
@@ -0,0 +1,29 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+from __future__ import unicode_literals |
|
| 3 |
+ |
|
| 4 |
+from django.db import models, migrations |
|
| 5 |
+ |
|
| 6 |
+ |
|
| 7 |
+class Migration(migrations.Migration): |
|
| 8 |
+ |
|
| 9 |
+ dependencies = [ |
|
| 10 |
+ ('account', '0020_tourguideinfo'),
|
|
| 11 |
+ ] |
|
| 12 |
+ |
|
| 13 |
+ operations = [ |
|
| 14 |
+ migrations.AddField( |
|
| 15 |
+ model_name='userinfo', |
|
| 16 |
+ name='islensman', |
|
| 17 |
+ field=models.BooleanField(default=False, help_text='\u6444\u5f71\u5e08\uff1f', db_index=True, verbose_name='islensman'), |
|
| 18 |
+ ), |
|
| 19 |
+ migrations.AddField( |
|
| 20 |
+ model_name='userinfo', |
|
| 21 |
+ name='istourguide', |
|
| 22 |
+ field=models.BooleanField(default=False, help_text='\u5bfc\u6e38\uff1f', db_index=True, verbose_name='istourguide'), |
|
| 23 |
+ ), |
|
| 24 |
+ migrations.AlterField( |
|
| 25 |
+ model_name='userinfo', |
|
| 26 |
+ name='user_from', |
|
| 27 |
+ field=models.IntegerField(default=0, help_text='\u7528\u6237\u6765\u6e90', verbose_name='user_from', choices=[(0, 'APP \u521b\u5efa\u7528\u6237'), (1, '\u5fae\u4fe1\u6388\u6743\u7528\u6237'), (9, '\u6e38\u5ba2\u7528\u6237'), (10, '\u6444\u5f71\u5e08\u7528\u6237'), (11, '\u5bfc\u6e38\u7528\u6237')]), |
|
| 28 |
+ ), |
|
| 29 |
+ ] |
@@ -135,6 +135,64 @@ class LensmanIncomeExpensesInfo(CreateUpdateMixin): |
||
| 135 | 135 |
return unicode(self.pk) |
| 136 | 136 |
|
| 137 | 137 |
|
| 138 |
+class TourGuideInfo(CreateUpdateMixin): |
|
| 139 |
+ MALE = 1 |
|
| 140 |
+ FEMALE = 0 |
|
| 141 |
+ |
|
| 142 |
+ SEX_TYPE = ( |
|
| 143 |
+ (MALE, u'男'), |
|
| 144 |
+ (FEMALE, u'女'), |
|
| 145 |
+ ) |
|
| 146 |
+ |
|
| 147 |
+ REFUSED = -1 |
|
| 148 |
+ UNVERIFIED = 0 |
|
| 149 |
+ ACTIVATED = 1 |
|
| 150 |
+ DISABLED = 2 |
|
| 151 |
+ DELETED = 3 |
|
| 152 |
+ ASSIGN = 10 |
|
| 153 |
+ |
|
| 154 |
+ USER_STATUS = ( |
|
| 155 |
+ (REFUSED, u'已拒绝'), |
|
| 156 |
+ (UNVERIFIED, u'未验证'), |
|
| 157 |
+ (ACTIVATED, u'已激活'), |
|
| 158 |
+ (DISABLED, u'已禁用'), |
|
| 159 |
+ (DELETED, u'已删除'), |
|
| 160 |
+ (ASSIGN, u'已分配'), |
|
| 161 |
+ ) |
|
| 162 |
+ |
|
| 163 |
+ tourguide_id = models.CharField(_(u'tourguide_id'), max_length=255, blank=True, null=True, help_text=u'导游唯一标识', db_index=True, unique=True) |
|
| 164 |
+ |
|
| 165 |
+ unionid = models.CharField(_(u'unionid'), max_length=255, blank=True, null=True, help_text=u'微信 Union ID', db_index=True, unique=True) |
|
| 166 |
+ |
|
| 167 |
+ name = models.CharField(_(u'name'), max_length=255, blank=True, null=True, help_text=u'导游姓名') |
|
| 168 |
+ sex = models.IntegerField(_(u'sex'), choices=SEX_TYPE, default=MALE, help_text=u'导游性别') |
|
| 169 |
+ phone = models.CharField(_(u'phone'), max_length=255, blank=True, null=True, help_text=u'导游电话', db_index=True, unique=True) |
|
| 170 |
+ location = models.CharField(_(u'location'), max_length=255, blank=True, null=True, help_text=u'导游地址') |
|
| 171 |
+ |
|
| 172 |
+ no = models.CharField(_(u'no'), max_length=255, blank=True, null=True, help_text=u'导游证编号') |
|
| 173 |
+ |
|
| 174 |
+ user_status = models.IntegerField(_(u'user_status'), choices=USER_STATUS, default=UNVERIFIED) |
|
| 175 |
+ refused_reason = models.TextField(_(u'refused_reason'), blank=True, null=True, help_text=u'审核拒绝原因') |
|
| 176 |
+ |
|
| 177 |
+ class Meta: |
|
| 178 |
+ verbose_name = _(u'tourguideinfo') |
|
| 179 |
+ verbose_name_plural = _(u'tourguideinfo') |
|
| 180 |
+ |
|
| 181 |
+ def __unicode__(self): |
|
| 182 |
+ return unicode(self.pk) |
|
| 183 |
+ |
|
| 184 |
+ @property |
|
| 185 |
+ def data(self): |
|
| 186 |
+ return {
|
|
| 187 |
+ 'name': self.name, |
|
| 188 |
+ 'sex': self.sex, |
|
| 189 |
+ 'phone': self.phone, |
|
| 190 |
+ 'location': self.location, |
|
| 191 |
+ 'status': self.user_status, |
|
| 192 |
+ 'refused_reason': self.refused_reason, |
|
| 193 |
+ } |
|
| 194 |
+ |
|
| 195 |
+ |
|
| 138 | 196 |
class WechatInfo(CreateUpdateMixin): |
| 139 | 197 |
MALE = 1 |
| 140 | 198 |
FEMALE = 0 |
@@ -167,12 +225,14 @@ class UserInfo(CreateUpdateMixin): |
||
| 167 | 225 |
WX_USER = 1 |
| 168 | 226 |
GUEST_USER = 9 |
| 169 | 227 |
LENSMAN_USER = 10 |
| 228 |
+ TOURGUIDE_USER = 11 |
|
| 170 | 229 |
|
| 171 | 230 |
USER_FROM = ( |
| 172 | 231 |
(APP_USER, u'APP 创建用户'), |
| 173 | 232 |
(WX_USER, u'微信授权用户'), |
| 174 | 233 |
(GUEST_USER, u'游客用户'), |
| 175 | 234 |
(LENSMAN_USER, u'摄影师用户'), |
| 235 |
+ (TOURGUIDE_USER, u'导游用户'), |
|
| 176 | 236 |
) |
| 177 | 237 |
|
| 178 | 238 |
UNVERIFIED = 0 |
@@ -218,6 +278,10 @@ class UserInfo(CreateUpdateMixin): |
||
| 218 | 278 |
city = models.CharField(_(u'city'), max_length=255, blank=True, null=True, help_text=u'用户城市') |
| 219 | 279 |
location = models.CharField(_(u'location'), max_length=255, blank=True, null=True, help_text=u'用户地址') |
| 220 | 280 |
|
| 281 |
+ # 用户身份 |
|
| 282 |
+ islensman = models.BooleanField(_(u'islensman'), default=False, help_text=_(u'摄影师?'), db_index=True) |
|
| 283 |
+ istourguide = models.BooleanField(_(u'istourguide'), default=False, help_text=_(u'导游?'), db_index=True) |
|
| 284 |
+ |
|
| 221 | 285 |
balance = models.IntegerField(_(u'balance'), default=0, help_text=u'用户余额(分)') |
| 222 | 286 |
freeze_income_balance = models.IntegerField(_(u'freeze_income_balance'), default=0, help_text=u'用户收入冻结余额(分)') |
| 223 | 287 |
freeze_expense_balance = models.IntegerField(_(u'freeze_expense_balance'), default=0, help_text=u'用户支出冻结余额(分)') |
@@ -250,6 +314,8 @@ class UserInfo(CreateUpdateMixin): |
||
| 250 | 314 |
return self.nickname |
| 251 | 315 |
elif self.user_from == self.LENSMAN_USER: |
| 252 | 316 |
return self.name |
| 317 |
+ elif self.user_from == self.TOURGUIDE_USER: |
|
| 318 |
+ return self.name |
|
| 253 | 319 |
return self.nickname |
| 254 | 320 |
|
| 255 | 321 |
@property |
@@ -0,0 +1,48 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+ |
|
| 3 |
+from __future__ import division |
|
| 4 |
+ |
|
| 5 |
+from django.conf import settings |
|
| 6 |
+from logit import logit |
|
| 7 |
+ |
|
| 8 |
+from account.models import TourGuideInfo |
|
| 9 |
+from utils.error.errno_utils import TourGuideStatusCode |
|
| 10 |
+from utils.error.response_utils import response |
|
| 11 |
+ |
|
| 12 |
+ |
|
| 13 |
+r = settings.REDIS_CACHE |
|
| 14 |
+ |
|
| 15 |
+ |
|
| 16 |
+@logit |
|
| 17 |
+def tourguide_submit_api(request): |
|
| 18 |
+ """ |
|
| 19 |
+ 导游信息提交 |
|
| 20 |
+ :param request: |
|
| 21 |
+ :return: |
|
| 22 |
+ """ |
|
| 23 |
+ unionid = request.POST.get('unionid', '')
|
|
| 24 |
+ openid = request.POST.get('openid', '')
|
|
| 25 |
+ phone = request.POST.get('phone', '')
|
|
| 26 |
+ |
|
| 27 |
+ if TourGuideInfo.objects.filter(phone=phone).exclude(unionid=unionid).exists(): |
|
| 28 |
+ return response(TourGuideStatusCode.TOURGUIDE_PHONE_ALREADY_EXISTS) |
|
| 29 |
+ |
|
| 30 |
+ fields = {
|
|
| 31 |
+ 'name': request.POST.get('name', ''),
|
|
| 32 |
+ 'sex': int(request.POST.get('sex', 1)),
|
|
| 33 |
+ 'phone': phone, |
|
| 34 |
+ 'location': request.POST.get('location', ''),
|
|
| 35 |
+ 'no': request.POST.get('no', ''),
|
|
| 36 |
+ 'user_status': TourGuideInfo.UNVERIFIED, |
|
| 37 |
+ } |
|
| 38 |
+ |
|
| 39 |
+ tourguide, created = TourGuideInfo.objects.get_or_create(unionid=unionid, defaults=fields) |
|
| 40 |
+ # 状态为 UNVERIFIED 的允许修改, 其他需要登录摄影师 APP 进行信息的修改 |
|
| 41 |
+ if tourguide.user_status not in [TourGuideInfo.UNVERIFIED, TourGuideInfo.REFUSED]: |
|
| 42 |
+ return response(TourGuideStatusCode.TOURGUIDE_ALREADY_NOT_UNVERIFIED) |
|
| 43 |
+ if not created: |
|
| 44 |
+ for key, value in fields.iteritems(): |
|
| 45 |
+ setattr(tourguide, key, value) |
|
| 46 |
+ tourguide.save() |
|
| 47 |
+ |
|
| 48 |
+ return response(200, 'Submit Success', u'提交成功', {})
|
@@ -39,7 +39,7 @@ def lensman_login_api(request): |
||
| 39 | 39 |
|
| 40 | 40 |
@logit |
| 41 | 41 |
def user_is_registered_api(request): |
| 42 |
- return response(200, '', '', {
|
|
| 42 |
+ return response(200, data={
|
|
| 43 | 43 |
'registered': UserInfo.objects.filter(username=request.POST.get('username', '')).exists(),
|
| 44 | 44 |
}) |
| 45 | 45 |
|
@@ -3,6 +3,7 @@ |
||
| 3 | 3 |
from django.conf.urls import url |
| 4 | 4 |
|
| 5 | 5 |
from account import views as account_views |
| 6 |
+from account import tourguide_views |
|
| 6 | 7 |
from group import views as group_views |
| 7 | 8 |
from group import lensman_views |
| 8 | 9 |
from message import views as message_views |
@@ -41,6 +42,11 @@ urlpatterns += [ |
||
| 41 | 42 |
url(r'^l/origin_wanted$', lensman_views.lensman_origin_wanted_api, name='lensman_origin_wanted_api'), # 摄影师原图订单 |
| 42 | 43 |
] |
| 43 | 44 |
|
| 45 |
+# 导游相关 |
|
| 46 |
+urlpatterns += [ |
|
| 47 |
+ url(r'^t/submit$', tourguide_views.tourguide_submit_api, name='tourguide_submit_api'), # 导游信息提交 |
|
| 48 |
+] |
|
| 49 |
+ |
|
| 44 | 50 |
# 群组相关 |
| 45 | 51 |
urlpatterns += [ |
| 46 | 52 |
url(r'^g/create$', group_views.group_create_api, name='group_create_api'), # 群组创建 |
@@ -0,0 +1,213 @@ |
||
| 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: rgb(0, 0, 0); |
|
| 20 |
+ } |
|
| 21 |
+ </style> |
|
| 22 |
+ </head> |
|
| 23 |
+ <body> |
|
| 24 |
+ <div class="container" > |
|
| 25 |
+ <div class="weui_cells_title">基本信息</div> |
|
| 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="{{ tourguide_info.name }}" placeholder="请输入姓名" {% if not modified %}disabled{% endif %}>
|
|
| 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" {% if not modified %}disabled{% endif %}>
|
|
| 37 |
+ <option value="1" {% ifequal tourguide_info.sex 1 %}selected{% endifequal %}>男</option>
|
|
| 38 |
+ <option value="0" {% ifequal tourguide_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="{{ tourguide_info.phone }}" placeholder="请输入手机号" {% if not modified %}disabled{% endif %}>
|
|
| 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="{{ tourguide_info.location }}" placeholder="请输入地址" {% if not modified %}disabled{% endif %}>#}
|
|
| 52 |
+{# </div>#}
|
|
| 53 |
+{# </div>#}
|
|
| 54 |
+ <div class="weui_cell"> |
|
| 55 |
+ <div class="weui_cell_hd"><label for="" class="weui_label">导游证编号</label></div> |
|
| 56 |
+ <div class="weui_cell_bd weui_cell_primary"> |
|
| 57 |
+ <input id="no" class="weui_input" type="text" required="required" value="{{ tourguide_info.no }}" placeholder="请输入导游证编号" {% if not modified %}disabled{% endif %}>
|
|
| 58 |
+ </div> |
|
| 59 |
+ </div> |
|
| 60 |
+ </div> |
|
| 61 |
+ |
|
| 62 |
+ {% if tourguide_info %}
|
|
| 63 |
+ <div class="weui_cells_title">审核状态</div> |
|
| 64 |
+ <div class="weui_cells"> |
|
| 65 |
+ <div class="weui_cell"> |
|
| 66 |
+ <div class="weui_cell_bd weui_cell_primary"> |
|
| 67 |
+ <p>状态</p> |
|
| 68 |
+ </div> |
|
| 69 |
+ <div class="weui_cell_ft"> |
|
| 70 |
+ {% ifequal tourguide_info.status -1 %}已拒绝{% endifequal %}
|
|
| 71 |
+ {% ifequal tourguide_info.status 0 %}审核中{% endifequal %}
|
|
| 72 |
+ {% ifequal tourguide_info.status 1 %}已激活{% endifequal %}
|
|
| 73 |
+ {% ifequal tourguide_info.status 2 %}已禁用{% endifequal %}
|
|
| 74 |
+ {% ifequal tourguide_info.status 3 %}已删除{% endifequal %}
|
|
| 75 |
+ </div> |
|
| 76 |
+ </div> |
|
| 77 |
+ </div> |
|
| 78 |
+ {% endif %}
|
|
| 79 |
+ |
|
| 80 |
+ |
|
| 81 |
+ {% ifequal tourguide_info.status -1 %}
|
|
| 82 |
+ <div class="weui_cells_title">拒绝原因</div> |
|
| 83 |
+ <div class="weui_cells"> |
|
| 84 |
+ <div class="weui_panel_bd"> |
|
| 85 |
+ <div class="weui_media_box weui_media_text"> |
|
| 86 |
+ <p class="weui_media_desc">{{ tourguide_info.refused_reason|safe|linebreaks }}</p>
|
|
| 87 |
+ </div> |
|
| 88 |
+ </div> |
|
| 89 |
+ </div> |
|
| 90 |
+ {% endifequal %}
|
|
| 91 |
+ |
|
| 92 |
+ <br> |
|
| 93 |
+ |
|
| 94 |
+ {% if modified %}<button id="submit" class="weui_btn weui_btn_warn">确认</button>{% endif %}
|
|
| 95 |
+ |
|
| 96 |
+ <div class="weui_dialog_alert" id="dialog" style="display: none"> |
|
| 97 |
+ <div class="weui_mask"></div> |
|
| 98 |
+ <div class="weui_dialog"> |
|
| 99 |
+ <div class="weui_dialog_hd"><strong id="title" class="weui_dialog_title">弹窗标题</strong></div> |
|
| 100 |
+ <div id="content" class="weui_dialog_bd">弹窗内容,告知当前页面信息等</div> |
|
| 101 |
+ <div class="weui_dialog_ft"> |
|
| 102 |
+ <a href="javascript:;" class="weui_btn_dialog primary">确定</a> |
|
| 103 |
+ </div> |
|
| 104 |
+ </div> |
|
| 105 |
+ </div> |
|
| 106 |
+ |
|
| 107 |
+ <div id="toast" style="display: none;"> |
|
| 108 |
+ <div class="weui_mask_transparent"></div> |
|
| 109 |
+ <div class="weui_toast"> |
|
| 110 |
+ <i class="weui_icon_toast"></i> |
|
| 111 |
+ <p class="weui_toast_content">已完成</p> |
|
| 112 |
+ </div> |
|
| 113 |
+ </div> |
|
| 114 |
+ </div> |
|
| 115 |
+ |
|
| 116 |
+ <script src="//cdn.bootcss.com/zepto/1.1.6/zepto.min.js"></script> |
|
| 117 |
+ <script> |
|
| 118 |
+ {% if modified %}
|
|
| 119 |
+ $(function() {
|
|
| 120 |
+ function getURLParameter(name) {
|
|
| 121 |
+ return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search) || [null, ''])[1].replace(/\+/g, '%20')) || null;
|
|
| 122 |
+ } |
|
| 123 |
+ |
|
| 124 |
+ function show_error_dialog(title, content) {
|
|
| 125 |
+ $('#dialog #title').text(title);
|
|
| 126 |
+ $('#dialog #content').text(content);
|
|
| 127 |
+ $('#dialog').show();
|
|
| 128 |
+ } |
|
| 129 |
+ |
|
| 130 |
+ function data_check() {
|
|
| 131 |
+ var unionid = getURLParameter('unionid');
|
|
| 132 |
+ if (!unionid) {
|
|
| 133 |
+ show_error_dialog('微信授权', '微信授权失败,请重新打开页面');
|
|
| 134 |
+ return false; |
|
| 135 |
+ } |
|
| 136 |
+ |
|
| 137 |
+ var name = $('#name').val();
|
|
| 138 |
+ if (!name) {
|
|
| 139 |
+ show_error_dialog('姓名', '姓名错误,请检查重新输入');
|
|
| 140 |
+ return false; |
|
| 141 |
+ } |
|
| 142 |
+ |
|
| 143 |
+ var phone_valid = $('#phone').is(':valid');
|
|
| 144 |
+ if (!phone_valid) {
|
|
| 145 |
+ show_error_dialog('手机号', '手机号错误,请检查重新输入');
|
|
| 146 |
+ return false; |
|
| 147 |
+ } |
|
| 148 |
+ |
|
| 149 |
+{# var location = $('#location').val();#}
|
|
| 150 |
+{# if (!location) {#}
|
|
| 151 |
+{# show_error_dialog('地址', '地址错误,请检查重新输入');#}
|
|
| 152 |
+{# return false;#}
|
|
| 153 |
+{# }#}
|
|
| 154 |
+ |
|
| 155 |
+ var no = $('#no').val();
|
|
| 156 |
+ if (!no) {
|
|
| 157 |
+ show_error_dialog('编号', '导游证编号错误,请检查重新输入');
|
|
| 158 |
+ return false; |
|
| 159 |
+ } |
|
| 160 |
+ |
|
| 161 |
+ return {
|
|
| 162 |
+ unionid: unionid, |
|
| 163 |
+ openid: getURLParameter('openid'),
|
|
| 164 |
+ name: name, |
|
| 165 |
+ sex: $('#sex option:checked').val(),
|
|
| 166 |
+ phone: $('#phone').val(),
|
|
| 167 |
+{# location: location,#}
|
|
| 168 |
+ no: no, |
|
| 169 |
+ } |
|
| 170 |
+ } |
|
| 171 |
+ |
|
| 172 |
+ $('#submit').click(function () {
|
|
| 173 |
+ var check_result = data_check(); |
|
| 174 |
+ if (check_result){
|
|
| 175 |
+ $.ajax({
|
|
| 176 |
+ type: 'POST', |
|
| 177 |
+ url: 't/submit', |
|
| 178 |
+ data: check_result, |
|
| 179 |
+ success: function(data) {
|
|
| 180 |
+ if (data.status == 200) {
|
|
| 181 |
+ $('#toast').show();
|
|
| 182 |
+ setTimeout(function () {
|
|
| 183 |
+ $('#toast').hide();
|
|
| 184 |
+ }, 1000); |
|
| 185 |
+ window.location.reload(); |
|
| 186 |
+ } else {
|
|
| 187 |
+ show_error_dialog('错误', data.description);
|
|
| 188 |
+ } |
|
| 189 |
+ } |
|
| 190 |
+ }) |
|
| 191 |
+ } |
|
| 192 |
+ }); |
|
| 193 |
+ |
|
| 194 |
+ $('#dialog .weui_btn_dialog').click(function () {
|
|
| 195 |
+ $('#dialog').hide();
|
|
| 196 |
+ }) |
|
| 197 |
+ }); |
|
| 198 |
+ {% endif %}
|
|
| 199 |
+ </script> |
|
| 200 |
+ <script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script> |
|
| 201 |
+ <script type="text/javascript" src="{% static 'pai2/js/jswe.js' %}?v=1"></script>
|
|
| 202 |
+ <script> |
|
| 203 |
+ V.initWxData({
|
|
| 204 |
+ imgUrl: "http://pai.ai/static/pai2/img/paiai_96_96.png", |
|
| 205 |
+ link: 'http://api.pai.ai/wx_oauth2?redirect_url=http://pai.ai/page/tourguide&scope=snsapi_base', |
|
| 206 |
+ desc: "导游授权", |
|
| 207 |
+ title: "导游授权", |
|
| 208 |
+ timeLine: "" |
|
| 209 |
+ }, true); |
|
| 210 |
+ V.hideOptionMenu(); |
|
| 211 |
+ </script> |
|
| 212 |
+ </body> |
|
| 213 |
+</html> |
@@ -2,7 +2,7 @@ |
||
| 2 | 2 |
|
| 3 | 3 |
from django.shortcuts import render |
| 4 | 4 |
|
| 5 |
-from account.models import LensmanInfo |
|
| 5 |
+from account.models import LensmanInfo, TourGuideInfo |
|
| 6 | 6 |
|
| 7 | 7 |
|
| 8 | 8 |
def user_agreement(request): |
@@ -29,3 +29,17 @@ def lensman_oauth(request): |
||
| 29 | 29 |
|
| 30 | 30 |
def lensman_price(request): |
| 31 | 31 |
return render(request, 'page/lensman_price.html', {})
|
| 32 |
+ |
|
| 33 |
+ |
|
| 34 |
+def tourguide_oauth(request): |
|
| 35 |
+ unionid = request.GET.get('unionid', '')
|
|
| 36 |
+ |
|
| 37 |
+ try: |
|
| 38 |
+ tourguide = TourGuideInfo.objects.get(unionid=unionid) |
|
| 39 |
+ except TourGuideInfo.DoesNotExist: |
|
| 40 |
+ tourguide = None |
|
| 41 |
+ |
|
| 42 |
+ return render(request, 'page/tourguide_oauth.html', {
|
|
| 43 |
+ 'tourguide_info': tourguide and tourguide.data, |
|
| 44 |
+ 'modified': bool((not tourguide) or (tourguide and tourguide.user_status in [TourGuideInfo.UNVERIFIED, TourGuideInfo.REFUSED])), # 是否可以更改信息 |
|
| 45 |
+ }) |
@@ -22,6 +22,7 @@ from django.contrib import admin |
||
| 22 | 22 |
from rest_framework import routers |
| 23 | 23 |
|
| 24 | 24 |
from account import views as account_views |
| 25 |
+from account import tourguide_views |
|
| 25 | 26 |
from group import views as group_views |
| 26 | 27 |
from group import lensman_views |
| 27 | 28 |
from page import views as page_views |
@@ -69,6 +70,8 @@ urlpatterns += [ |
||
| 69 | 70 |
|
| 70 | 71 |
url(r'^page/lensman$', page_views.lensman_oauth, name='lensman_oauth'), # 摄影师授权页面 |
| 71 | 72 |
url(r'^page/price$', page_views.lensman_price, name='lensman_price'), # 摄影师照片价格和分成规则 |
| 73 |
+ |
|
| 74 |
+ url(r'^page/tourguide$', page_views.tourguide_oauth, name='tourguide_oauth'), # 导游授权页面 |
|
| 72 | 75 |
] |
| 73 | 76 |
|
| 74 | 77 |
urlpatterns += [ |
@@ -84,6 +87,11 @@ urlpatterns += [ |
||
| 84 | 87 |
url(r'^page/l/submit$', lensman_views.lensman_submit_api, name='lensman_submit_api'), # 摄影师信息提交 |
| 85 | 88 |
] |
| 86 | 89 |
|
| 90 |
+# 导游相关 |
|
| 91 |
+urlpatterns += [ |
|
| 92 |
+ url(r'^page/t/submit$', tourguide_views.tourguide_submit_api, name='tourguide_submit_api'), # 导游信息提交 |
|
| 93 |
+] |
|
| 94 |
+ |
|
| 87 | 95 |
# Wire up our API using automatic URL routing. |
| 88 | 96 |
# Additionally, we include login URLs for the browsable API. |
| 89 | 97 |
urlpatterns += [ |
@@ -15,25 +15,37 @@ class LensmanStatusCode(BaseStatusCode): |
||
| 15 | 15 |
LENSMAN_NOT_ACTIVATED = StatusCodeField(400015, u'Lensman Not Activated', description=u'摄影师帐号未激活') |
| 16 | 16 |
|
| 17 | 17 |
|
| 18 |
+class TourGuideStatusCode(BaseStatusCode): |
|
| 19 |
+ """ 导游相关错误码 4001xx """ |
|
| 20 |
+ TOURGUIDE_NOT_FOUND = StatusCodeField(400101, u'Tour Guide Not Found', description=u'导游不存在') |
|
| 21 |
+ TOURGUIDE_PASSWORD_ERROR = StatusCodeField(400102, u'Tour Guide Password Error', description=u'导游密码错误') |
|
| 22 |
+ |
|
| 23 |
+ TOURGUIDE_PHONE_ALREADY_EXISTS = StatusCodeField(400105, u'Tour Guide Phone Already Exists', description=u'手机号已经存在') |
|
| 24 |
+ |
|
| 25 |
+ TOURGUIDE_ALREADY_NOT_UNVERIFIED = StatusCodeField(400110, u'Tour Guide Already Not Unverified', description=u'导游帐号已激活') |
|
| 26 |
+ |
|
| 27 |
+ TOURGUIDE_NOT_ACTIVATED = StatusCodeField(400115, u'Tour Guide Not Activated', description=u'导游帐号未激活') |
|
| 28 |
+ |
|
| 29 |
+ |
|
| 18 | 30 |
class UserStatusCode(BaseStatusCode): |
| 19 |
- """ 用户相关错误码 4001xx """ |
|
| 20 |
- USER_NOT_FOUND = StatusCodeField(400101, u'User Not Found', description=u'用户不存在') |
|
| 21 |
- USER_PASSWORD_ERROR = StatusCodeField(400102, u'User Password Error', description=u'用户密码错误') |
|
| 22 |
- USERNAME_HAS_REGISTERED = StatusCodeField(400103, u'Username Has Registered', description=u'用户名已注册') |
|
| 31 |
+ """ 用户相关错误码 4005xx """ |
|
| 32 |
+ USER_NOT_FOUND = StatusCodeField(400501, u'User Not Found', description=u'用户不存在') |
|
| 33 |
+ USER_PASSWORD_ERROR = StatusCodeField(400502, u'User Password Error', description=u'用户密码错误') |
|
| 34 |
+ USERNAME_HAS_REGISTERED = StatusCodeField(400503, u'Username Has Registered', description=u'用户名已注册') |
|
| 23 | 35 |
|
| 24 |
- GUEST_NOT_ALLOWED = StatusCodeField(400111, u'Guest Not ALLOWED', description=u'游客登录未开启') |
|
| 36 |
+ GUEST_NOT_ALLOWED = StatusCodeField(400511, u'Guest Not ALLOWED', description=u'游客登录未开启') |
|
| 25 | 37 |
|
| 26 | 38 |
|
| 27 | 39 |
class PhoneStatusCode(BaseStatusCode): |
| 28 |
- """ 手机相关错误码 4002xx """ |
|
| 29 |
- PHONE_NOT_FOUND = StatusCodeField(400201, u'Phone Not Found', description=u'手机不存在') |
|
| 40 |
+ """ 手机相关错误码 4006xx """ |
|
| 41 |
+ PHONE_NOT_FOUND = StatusCodeField(400601, u'Phone Not Found', description=u'手机不存在') |
|
| 30 | 42 |
|
| 31 | 43 |
|
| 32 | 44 |
class WechatStatusCode(BaseStatusCode): |
| 33 |
- """ 微信相关错误码 4003xx """ |
|
| 34 |
- WECHAT_NOT_FOUND = StatusCodeField(400301, u'Wechat Not Found', description=u'微信不存在') |
|
| 35 |
- UNIONID_NOT_FOUND = StatusCodeField(400302, u'Unionid Not Found', description=u'微信 UNIONID 不存在') |
|
| 36 |
- OPENID_NOT_FOUND = StatusCodeField(400303, u'OPENID Not Found', description=u'微信 OPENID 不存在') |
|
| 45 |
+ """ 微信相关错误码 4007xx """ |
|
| 46 |
+ WECHAT_NOT_FOUND = StatusCodeField(400701, u'Wechat Not Found', description=u'微信不存在') |
|
| 47 |
+ UNIONID_NOT_FOUND = StatusCodeField(400702, u'Unionid Not Found', description=u'微信 UNIONID 不存在') |
|
| 48 |
+ OPENID_NOT_FOUND = StatusCodeField(400703, u'OPENID Not Found', description=u'微信 OPENID 不存在') |
|
| 37 | 49 |
|
| 38 | 50 |
|
| 39 | 51 |
class PhotoStatusCode(BaseStatusCode): |