>BIN   simditor/static/simditor/images/emoji/dog.png
  • BIN
      simditor/static/simditor/images/emoji/dog2.png
  • BIN
      simditor/static/simditor/images/emoji/dollar.png
  • BIN
      simditor/static/simditor/images/emoji/dolls.png
  • BIN
      simditor/static/simditor/images/emoji/dolphin.png
  • BIN
      simditor/static/simditor/images/emoji/door.png
  • BIN
      simditor/static/simditor/images/emoji/doughnut.png
  • BIN
      simditor/static/simditor/images/emoji/dragon.png
  • BIN
      simditor/static/simditor/images/emoji/dragon_face.png
  • BIN
      simditor/static/simditor/images/emoji/dress.png
  • BIN
      simditor/static/simditor/images/emoji/dromedary_camel.png
  • BIN
      simditor/static/simditor/images/emoji/droplet.png
  • BIN
      simditor/static/simditor/images/emoji/dvd.png
  • BIN
      simditor/static/simditor/images/emoji/e-mail.png
  • BIN
      simditor/static/simditor/images/emoji/ear.png
  • BIN
      simditor/static/simditor/images/emoji/ear_of_rice.png
  • BIN
      simditor/static/simditor/images/emoji/earth_africa.png
  • BIN
      simditor/static/simditor/images/emoji/earth_americas.png
  • BIN
      simditor/static/simditor/images/emoji/earth_asia.png
  • BIN
      simditor/static/simditor/images/emoji/egg.png
  • BIN
      simditor/static/simditor/images/emoji/eggplant.png
  • BIN
      simditor/static/simditor/images/emoji/eight.png
  • BIN
      simditor/static/simditor/images/emoji/eight_pointed_black_star.png
  • BIN
      simditor/static/simditor/images/emoji/eight_spoked_asterisk.png
  • BIN
      simditor/static/simditor/images/emoji/eightball.png
  • BIN
      simditor/static/simditor/images/emoji/electric_plug.png
  • BIN
      simditor/static/simditor/images/emoji/elephant.png
  • BIN
      simditor/static/simditor/images/emoji/email.png
  • 0 0
      simditor/static/simditor/images/emoji/emojify.css
  • + 1 - 1
    account/admin.py

    @@ -8,7 +8,7 @@ from mch.models import ConsumeInfoSubmitLogInfo
    8 8
     
    9 9
     
    10 10
     class UserInfoAdmin(ChangeOnlyModelAdmin, admin.ModelAdmin):
    11
    -    list_display = ('user_id', 'nickname', 'phone', 'unionid', 'openid', 'openid_miniapp', 'location', 'balance', 'user_status', 'test_user', 'status', 'created_at', 'updated_at')
    11
    +    list_display = ('user_id', 'nickname', 'phone', 'unionid', 'openid', 'openid_miniapp', 'location', 'balance', 'integral', 'freeze_integral', 'user_status', 'test_user', 'status', 'created_at', 'updated_at')
    12 12
         list_filter = ('test_user', 'sex', 'user_status', 'status')
    13 13
         readonly_fields = ('user_id', )
    14 14
         search_fields = ('user_id', 'username', 'unionid', 'openid', 'openid_miniapp', 'name', 'phone', 'location')

    + 35 - 0
    account/migrations/0037_auto_20191119_1348.py

    @@ -0,0 +1,35 @@
    1
    +# -*- coding: utf-8 -*-
    2
    +# Generated by Django 1.11.26 on 2019-11-19 05:48
    3
    +from __future__ import unicode_literals
    4
    +
    5
    +from django.db import migrations, models
    6
    +
    7
    +
    8
    +class Migration(migrations.Migration):
    9
    +
    10
    +    dependencies = [
    11
    +        ('account', '0036_auto_20190826_1537'),
    12
    +    ]
    13
    +
    14
    +    operations = [
    15
    +        migrations.AddField(
    16
    +            model_name='userinfo',
    17
    +            name='freeze_integral',
    18
    +            field=models.IntegerField(default=0, help_text='\u4f1a\u5458\u51bb\u7ed3\u79ef\u5206', verbose_name='freeze_integral'),
    19
    +        ),
    20
    +        migrations.AddField(
    21
    +            model_name='userinfo',
    22
    +            name='integral',
    23
    +            field=models.IntegerField(default=0, help_text='\u4f1a\u5458\u79ef\u5206', verbose_name='integral'),
    24
    +        ),
    25
    +        migrations.AddField(
    26
    +            model_name='userinfo',
    27
    +            name='level',
    28
    +            field=models.IntegerField(choices=[(0, '\u975e\u4f1a\u5458'), (1, 'LRC\u4f1a\u5458'), (2, '\u94f6\u5361\u4f1a\u5458'), (3, '\u91d1\u5361\u4f1a\u5458'), (4, '\u767d\u91d1\u5361\u4f1a\u5458'), (5, '\u9ed1\u91d1\u5361\u4f1a\u5458')], default=0, help_text='\u4f1a\u5458\u7b49\u7ea7', verbose_name='level'),
    29
    +        ),
    30
    +        migrations.AddField(
    31
    +            model_name='userinfo',
    32
    +            name='shots_num',
    33
    +            field=models.IntegerField(default=0, help_text='\u4e3b\u6301\u955c\u5934\u6570', verbose_name='shots_num'),
    34
    +        ),
    35
    +    ]

    + 27 - 0
    account/models.py

    @@ -290,6 +290,22 @@ class UserInfo(BaseModelMixin, LensmanTypeBoolMixin):
    290 290
             (FEMALE, u'女'),
    291 291
         )
    292 292
     
    293
    +    MEMBER_NO = 0
    294
    +    MEMBER_LRC = 1
    295
    +    MEMBER_SILVER = 2
    296
    +    MEMBER_GOLD = 3
    297
    +    MEMBER_WHITE_GOLD = 4
    298
    +    MEMBER_BLACK_GOLD = 5
    299
    +
    300
    +    LEVEL_TUPLE = (
    301
    +        (MEMBER_NO, u'非会员'),
    302
    +        (MEMBER_LRC, u'LRC会员'),
    303
    +        (MEMBER_SILVER, u'银卡会员'),
    304
    +        (MEMBER_GOLD, u'金卡会员'),
    305
    +        (MEMBER_WHITE_GOLD, u'白金卡会员'),
    306
    +        (MEMBER_BLACK_GOLD, u'黑金卡会员'),
    307
    +    )
    308
    +
    293 309
         user_id = models.CharField(_(u'user_id'), max_length=32, blank=True, null=True, help_text=u'用户唯一标识', db_index=True, unique=True)
    294 310
     
    295 311
         user_from = models.IntegerField(_(u'user_from'), choices=USER_FROM, default=APP_USER, help_text=u'用户来源')
    @@ -341,6 +357,13 @@ class UserInfo(BaseModelMixin, LensmanTypeBoolMixin):
    341 357
     
    342 358
         test_user = models.BooleanField(_(u'test_user'), default=False, help_text=_(u'是否为测试用户'), db_index=True)
    343 359
     
    360
    +    # 会员信息
    361
    +    integral = models.IntegerField(_(u'integral'), default=0, help_text=u'会员积分')
    362
    +    freeze_integral = models.IntegerField(_(u'freeze_integral'), default=0, help_text=u'会员冻结积分')
    363
    +
    364
    +    shots_num = models.IntegerField(_(u'shots_num'), default=0, help_text=u'主持镜头数')
    365
    +    level = models.IntegerField(_(u'level'), choices=LEVEL_TUPLE, default=MEMBER_NO, help_text=u'会员等级')
    366
    +
    344 367
         class Meta:
    345 368
             verbose_name = _(u'userinfo')
    346 369
             verbose_name_plural = _(u'userinfo')
    @@ -349,6 +372,10 @@ class UserInfo(BaseModelMixin, LensmanTypeBoolMixin):
    349 372
             return unicode(self.pk)
    350 373
     
    351 374
         @property
    375
    +    def final_integral(self):
    376
    +        return self.integral + self.freeze_integral
    377
    +
    378
    +    @property
    352 379
         def final_nickname(self):
    353 380
             if self.user_from == self.APP_USER:
    354 381
                 return self.username

    + 200 - 0
    api/member_views.py

    @@ -0,0 +1,200 @@
    1
    +# -*- coding: utf-8 -*-
    2
    +
    3
    +from __future__ import division
    4
    +
    5
    +from django.conf import settings
    6
    +from django_logit import logit
    7
    +from django_response import response
    8
    +from paginator import pagination
    9
    +
    10
    +from account.models import UserInfo
    11
    +from member.models import GoodsInfo, MemberActivityInfo, RightInfo
    12
    +from utils.error.errno_utils import UserStatusCode
    13
    +from utils.redis.rshot import get_shot_member_data
    14
    +
    15
    +
    16
    +@logit
    17
    +def member(request):
    18
    +    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
    19
    +    user_id = request.POST.get('user_id', '')
    20
    +
    21
    +    # 校验用户是否存在
    22
    +    try:
    23
    +        user = UserInfo.objects.get(user_id=user_id)
    24
    +    except UserInfo.DoesNotExist:
    25
    +        return response(UserStatusCode.USER_NOT_FOUND)
    26
    +
    27
    +    rights = RightInfo.objects.filter(status=True).order_by('position')
    28
    +    rights = [right.data for right in rights]
    29
    +
    30
    +    goods = GoodsInfo.objects.filter(status=True).order_by('position')
    31
    +    goods = [good.data for good in goods]
    32
    +
    33
    +    return response(200, data={
    34
    +        'nickname': user.final_nickname,
    35
    +        'avatar': user.avatar,
    36
    +        'integral': user.integral,
    37
    +        'freeze_integral': user.freeze_integral,
    38
    +        'final_integral': user.final_integral,
    39
    +        'shots_num': user.shots_num,
    40
    +        'level': user.level,
    41
    +        'rights': rights,
    42
    +        'goods': goods,
    43
    +    })
    44
    +
    45
    +
    46
    +@logit
    47
    +def rights(request):
    48
    +    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
    49
    +    user_id = request.POST.get('user_id', '')
    50
    +    level = request.POST.get('level', '')
    51
    +
    52
    +    # 校验用户是否存在
    53
    +    try:
    54
    +        user = UserInfo.objects.get(user_id=user_id)
    55
    +    except UserInfo.DoesNotExist:
    56
    +        return response(UserStatusCode.USER_NOT_FOUND)
    57
    +
    58
    +    rights = RightInfo.objects.filter(status=True).order_by('position')
    59
    +    rights = [right.data for right in rights]
    60
    +
    61
    +    return response(200, data={
    62
    +        'nickname': user.final_nickname,
    63
    +        'avatar': user.avatar,
    64
    +        'integral': user.integral,
    65
    +        'freeze_integral': user.freeze_integral,
    66
    +        'final_integral': user.final_integral,
    67
    +        'shots_num': user.shots_num,
    68
    +        'level': user.level,
    69
    +        'rights': rights,
    70
    +    })
    71
    +
    72
    +
    73
    +@logit
    74
    +def right_detail(request):
    75
    +    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
    76
    +    user_id = request.POST.get('user_id', '')
    77
    +    right_id = request.POST.get('right_id', '')
    78
    +
    79
    +    try:
    80
    +        right = RightInfo.objects.get(right_id=right_id)
    81
    +    except RightInfo.DoesNotExist:
    82
    +        return response()
    83
    +
    84
    +    return response(200, data={
    85
    +        'right': right.data,
    86
    +    })
    87
    +
    88
    +
    89
    +@logit
    90
    +def goods(request):
    91
    +    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
    92
    +    user_id = request.POST.get('user_id', '')
    93
    +
    94
    +    # 校验用户是否存在
    95
    +    try:
    96
    +        user = UserInfo.objects.get(user_id=user_id)
    97
    +    except UserInfo.DoesNotExist:
    98
    +        return response(UserStatusCode.USER_NOT_FOUND)
    99
    +
    100
    +    raw_goods = GoodsInfo.objects.filter(status=True).order_by('position')
    101
    +    banners = goods = []
    102
    +    for good in raw_goods:
    103
    +        if good.is_slider:
    104
    +            banners.append(good.data)
    105
    +        else:
    106
    +            goods.append(good.data)
    107
    +
    108
    +    return response(200, data={
    109
    +        'nickname': user.final_nickname,
    110
    +        'avatar': user.avatar,
    111
    +        'integral': user.integral,
    112
    +        'freeze_integral': user.freeze_integral,
    113
    +        'final_integral': user.final_integral,
    114
    +        'shots_num': user.shots_num,
    115
    +        'level': user.level,
    116
    +        'banners': banners,
    117
    +        'goods': goods,
    118
    +    })
    119
    +
    120
    +
    121
    +@logit
    122
    +def good_detail(request):
    123
    +    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
    124
    +    user_id = request.POST.get('user_id', '')
    125
    +    good_id = request.POST.get('good_id', '')
    126
    +
    127
    +    # 校验用户是否存在
    128
    +    try:
    129
    +        user = UserInfo.objects.get(user_id=user_id)
    130
    +    except UserInfo.DoesNotExist:
    131
    +        return response(UserStatusCode.USER_NOT_FOUND)
    132
    +
    133
    +    try:
    134
    +        good = GoodsInfo.objects.get(good_id=good_id)
    135
    +    except GoodsInfo.DoesNotExist:
    136
    +        return response()
    137
    +
    138
    +    return response(200, data={
    139
    +        'nickname': user.final_nickname,
    140
    +        'avatar': user.avatar,
    141
    +        'integral': user.integral,
    142
    +        'freeze_integral': user.freeze_integral,
    143
    +        'final_integral': user.final_integral,
    144
    +        'shots_num': user.shots_num,
    145
    +        'level': user.level,
    146
    +        'good': good.data,
    147
    +    })
    148
    +
    149
    +
    150
    +@logit
    151
    +def integrals(request):
    152
    +    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
    153
    +
    154
    +    return response(200, data={
    155
    +        'shots_types': get_shot_member_data(),
    156
    +        'enable_photo_upvote_integral': True,
    157
    +        'photo_upvote_integrals': {
    158
    +            'headers': ['排名', '日', '周', '月'],
    159
    +            'ranks': [
    160
    +                ['第1名', '10', '20', '30'],
    161
    +                ['第2名', '5', '10', '15'],
    162
    +                ['第3名', '3', '6', '9'],
    163
    +                ['第4-10名', '1', '2', '3'],
    164
    +            ]
    165
    +        },
    166
    +        'enable_activity_integral': True,
    167
    +    })
    168
    +
    169
    +
    170
    +@logit
    171
    +def activity_list(request):
    172
    +    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
    173
    +
    174
    +    raw_activitys = MemberActivityInfo.objects.filter(status=True).order_by('position')
    175
    +    banners = activitys = []
    176
    +    for act in raw_activitys:
    177
    +        if act.is_slider:
    178
    +            banners.append(act.data)
    179
    +        else:
    180
    +            goods.append(act.data)
    181
    +
    182
    +    return response(200, data={
    183
    +        'banners': banners,
    184
    +        'activitys': activitys,
    185
    +    })
    186
    +
    187
    +
    188
    +@logit
    189
    +def activity_detail(request):
    190
    +    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
    191
    +    activity_id = request.POST.get('activity_id')
    192
    +
    193
    +    try:
    194
    +        act = MemberActivityInfo.objects.get(pk=activity_id, status=True)
    195
    +    except MemberActivityInfo.DoesNotExist:
    196
    +        return response()
    197
    +
    198
    +    return response(200, data={
    199
    +        'activity': act.data,
    200
    +    })

    + 21 - 2
    api/urls.py

    @@ -5,8 +5,8 @@ from django_file_upload import views as file_views
    5 5
     
    6 6
     from account import tourguide_views
    7 7
     from account import views as account_views
    8
    -from api import (admin_views, clerk_views, distributor_views, encrypt_views, mch_views, model_views, operator_views,
    9
    -                 sr_views)
    8
    +from api import (admin_views, clerk_views, distributor_views, encrypt_views, mch_views, member_views, model_views,
    9
    +                 operator_views, sr_views)
    10 10
     from box import views as box_views
    11 11
     from geo import views as geo_views
    12 12
     from group import (groupuser_views, lensman_views, tourguidegroup_views, tourguidegroupadmin_views,
    @@ -298,3 +298,22 @@ urlpatterns += [
    298 298
     urlpatterns += [
    299 299
         url(r'^supersr/sr/tj$', sales_views.supersr_sr_tj, name='supersr_sr_tj'),
    300 300
     ]
    301
    +
    302
    +urlpatterns += [
    303
    +    url(r'^member$', member_views.member, name='member'),
    304
    +
    305
    +    url(r'^member/rights$', member_views.rights, name='member_rights'),
    306
    +    url(r'^member/right/detail$', member_views.right_detail, name='member_right_detail'),
    307
    +    url(r'^member/goods$', member_views.goods, name='member_goods'),
    308
    +    url(r'^member/good/detail$', member_views.good_detail, name='member_good_detail'),
    309
    +    url(r'^member/integrals$', member_views.integrals, name='member_integrals'),
    310
    +
    311
    +    url(r'^member/activity/list$', member_views.activity_list, name='member_activity_list'),
    312
    +    url(r'^member/activity/detail$', member_views.activity_detail, name='member_activity_detail'),
    313
    +
    314
    +    url(r'^rights$', member_views.rights, name='rights'),
    315
    +    url(r'^right/detail$', member_views.right_detail, name='right_detail'),
    316
    +    url(r'^goods$', member_views.goods, name='goods'),
    317
    +    url(r'^good/detail$', member_views.good_detail, name='good_detail'),
    318
    +    url(r'^integrals$', member_views.integrals, name='integrals'),
    319
    +]

    + 25 - 0
    integral/migrations/0011_auto_20191119_1348.py

    @@ -0,0 +1,25 @@
    1
    +# -*- coding: utf-8 -*-
    2
    +# Generated by Django 1.11.26 on 2019-11-19 05:48
    3
    +from __future__ import unicode_literals
    4
    +
    5
    +from django.db import migrations, models
    6
    +
    7
    +
    8
    +class Migration(migrations.Migration):
    9
    +
    10
    +    dependencies = [
    11
    +        ('integral', '0010_auto_20190909_1456'),
    12
    +    ]
    13
    +
    14
    +    operations = [
    15
    +        migrations.AddField(
    16
    +            model_name='saleclerksubmitloginfo',
    17
    +            name='has_scan',
    18
    +            field=models.BooleanField(db_index=True, default=False, help_text='\u662f\u5426\u88ab\u6d88\u8d39\u8005\u626b\u8fc7', verbose_name='has_scan'),
    19
    +        ),
    20
    +        migrations.AddField(
    21
    +            model_name='saleclerksubmitloginfo',
    22
    +            name='trackingNo',
    23
    +            field=models.CharField(blank=True, help_text='\u5feb\u9012\u5355\u53f7', max_length=32, null=True, verbose_name='trackingNo'),
    24
    +        ),
    25
    +    ]

    + 21 - 0
    kodo/settings.py

    @@ -49,6 +49,7 @@ INSTALLED_APPS = (
    49 49
         'django_rlog',
    50 50
         'django_we',
    51 51
         'corsheaders',
    52
    +    'simditor',
    52 53
         'api',
    53 54
         'account',
    54 55
         'box',
    @@ -58,6 +59,7 @@ INSTALLED_APPS = (
    58 59
         'integral',
    59 60
         'logs',
    60 61
         'mch',
    62
    +    'member',
    61 63
         'message',
    62 64
         'miniapp',
    63 65
         'operation',
    @@ -346,6 +348,25 @@ CORS_ORIGIN_WHITELIST = (
    346 348
     )
    347 349
     CORS_ALLOW_CREDENTIALS = True
    348 350
     
    351
    +# 富文本编辑器
    352
    +SIMDITOR_UPLOAD_PATH = 'uploads/'
    353
    +SIMDITOR_TOOLBAR = [
    354
    +    'markdown', 'title', 'bold', 'italic', 'underline', 'strikethrough', 'fontScale',
    355
    +    'color', '|', 'ol', 'ul', 'blockquote', 'code', 'table', '|', 'link',
    356
    +    'image', 'hr', '|', 'indent', 'outdent', 'alignment', 'checklist', 'fullscreen', 'emoji'
    357
    +]
    358
    +SIMDITOR_CONFIGS = {
    359
    +    'toolbar': SIMDITOR_TOOLBAR,
    360
    +    'upload': {
    361
    +        'url': '/simditor/upload/',
    362
    +        'fileKey': 'upload',
    363
    +        'image_size': 1024 * 1024 * 4  # max image size 4MB
    364
    +    },
    365
    +    'emoji': {
    366
    +        'imagePath': '/static/simditor/images/emoji/'
    367
    +    }
    368
    +}
    369
    +
    349 370
     # 错误信息邮件设置
    350 371
     # Email address that error messages come from.
    351 372
     SERVER_EMAIL = 'kimi@pai.ai'

    + 8 - 1
    mch/admin.py

    @@ -10,6 +10,7 @@ from pysnippets.strsnippets import strip
    10 10
     
    11 11
     from mch.models import (ActivityInfo, AdministratorInfo, BrandInfo, ConsumeInfoSubmitLogInfo, DistributorInfo,
    12 12
                             LatestAppInfo, LatestAppScreenInfo, ModelInfo, OperatorInfo, SaleclerkInfo)
    13
    +from utils.redis.rshot import update_shot_member_data
    13 14
     
    14 15
     
    15 16
     class AdministratorInfoAdmin(admin.ModelAdmin):
    @@ -64,7 +65,7 @@ class BrandInfoAdmin(admin.ModelAdmin):
    64 65
     
    65 66
     class ModelInfoAdmin(admin.ModelAdmin):
    66 67
         list_display = ('brand_id', 'brand_name', 'jancode', 'model_id', 'model_name', 'model_uni_name', 'model_full_name', 'model_descr', 'category', 'warehouse', 'image', 'url', 'image2', 'factory_yuan', 'integral', 'position', 'display', 'status', 'created_at', 'updated_at')
    67
    -    list_filter = ('brand_name', 'category', 'warehouse', 'display', 'status')
    68
    +    list_filter = ('brand_name', 'category', 'warehouse', 'shot_type_id', 'display', 'status')
    68 69
         readonly_fields = ('brand_name', 'factory_fee')
    69 70
         search_fields = ('brand_id', 'brand_name', 'jancode', 'model_id', 'model_name', 'model_uni_name', 'model_full_name', 'model_descr', 'category', 'warehouse')
    70 71
     
    @@ -80,6 +81,12 @@ class ModelInfoAdmin(admin.ModelAdmin):
    80 81
     
    81 82
             obj.save()
    82 83
     
    84
    +        update_shot_member_data()
    85
    +
    86
    +    def delete_model(self, request, obj):
    87
    +        obj.delete()
    88
    +        update_shot_member_data()
    89
    +
    83 90
     
    84 91
     class ModelImageInfoAdmin(admin.ModelAdmin):
    85 92
         list_display = ('model_id', 'model_name', 'image', 'url', 'position', 'status', 'created_at', 'updated_at')

    + 36 - 0
    mch/migrations/0039_auto_20191119_1348.py

    @@ -0,0 +1,36 @@
    1
    +# -*- coding: utf-8 -*-
    2
    +# Generated by Django 1.11.26 on 2019-11-19 05:48
    3
    +from __future__ import unicode_literals
    4
    +
    5
    +from django.db import migrations, models
    6
    +import django_models_ext.fileext
    7
    +
    8
    +
    9
    +class Migration(migrations.Migration):
    10
    +
    11
    +    dependencies = [
    12
    +        ('mch', '0038_auto_20190826_1625'),
    13
    +    ]
    14
    +
    15
    +    operations = [
    16
    +        migrations.AddField(
    17
    +            model_name='modelinfo',
    18
    +            name='shot_member_image',
    19
    +            field=models.ImageField(blank=True, help_text='\u955c\u5934\u4f1a\u5458\u56fe\u7247', null=True, upload_to=django_models_ext.fileext.upload_path, verbose_name='shot_member_image'),
    20
    +        ),
    21
    +        migrations.AddField(
    22
    +            model_name='modelinfo',
    23
    +            name='shot_member_integral',
    24
    +            field=models.IntegerField(default=0, help_text='\u955c\u5934\u4f1a\u5458\u79ef\u5206', verbose_name='shot_member_integral'),
    25
    +        ),
    26
    +        migrations.AddField(
    27
    +            model_name='modelinfo',
    28
    +            name='shot_type_id',
    29
    +            field=models.CharField(blank=True, db_index=True, help_text='\u955c\u5934\u7c7b\u578b\u552f\u4e00\u6807\u8bc6', max_length=32, null=True, verbose_name='shot_type_id'),
    30
    +        ),
    31
    +        migrations.AddField(
    32
    +            model_name='saleclerkinfo',
    33
    +            name='is_online_sales',
    34
    +            field=models.BooleanField(db_index=True, default=False, help_text='\u662f\u5426\u4e3a\u7f51\u9500', verbose_name='is_online_sales'),
    35
    +        ),
    36
    +    ]

    + 21 - 0
    mch/models.py

    @@ -161,6 +161,10 @@ class ModelInfo(BaseModelMixin):
    161 161
     
    162 162
         is_important = models.BooleanField(_(u'is_important'), default=False, help_text=_(u'是否重要型号'), db_index=True)
    163 163
     
    164
    +    shot_type_id = models.CharField(_(u'shot_type_id'), max_length=32, blank=True, null=True, help_text=u'镜头类型唯一标识', db_index=True)
    165
    +    shot_member_integral = models.IntegerField(_(u'shot_member_integral'), default=0, help_text=u'镜头会员积分')
    166
    +    shot_member_image = models.ImageField(_(u'shot_member_image'), upload_to=upload_path, blank=True, null=True, help_text=u'镜头会员图片')
    167
    +
    164 168
         class Meta:
    165 169
             verbose_name = _(u'型号信息')
    166 170
             verbose_name_plural = _(u'型号信息')
    @@ -185,6 +189,14 @@ class ModelInfo(BaseModelMixin):
    185 189
             return upload_file_url(self.image2)
    186 190
     
    187 191
         @property
    192
    +    def shot_member_image_path(self):
    193
    +        return upload_file_path(self.shot_member_image)
    194
    +
    195
    +    @property
    196
    +    def shot_member_image_url(self):
    197
    +        return upload_file_url(self.shot_member_image)
    198
    +
    199
    +    @property
    188 200
         def data(self):
    189 201
             return {
    190 202
                 'jancode': self.jancode,
    @@ -228,6 +240,15 @@ class ModelInfo(BaseModelMixin):
    228 240
     
    229 241
         fulldata = admindata
    230 242
     
    243
    +    @property
    244
    +    def shot_member_data(self):
    245
    +        return {
    246
    +            'shot_id': self.model_id,
    247
    +            'shot_name': self.model_name,
    248
    +            'shot_image': self.shot_member_image_url,
    249
    +            'integral': self.shot_member_integral,
    250
    +        }
    251
    +
    231 252
     
    232 253
     class ModelImageInfo(BaseModelMixin):
    233 254
         model_id = models.CharField(_(u'model_id'), max_length=32, blank=True, null=True, help_text=u'型号唯一标识', db_index=True)

    + 0 - 0
    member/__init__.py


    + 38 - 0
    member/admin.py

    @@ -0,0 +1,38 @@
    1
    +# -*- coding: utf-8 -*-
    2
    +
    3
    +from django.contrib import admin
    4
    +
    5
    +from member.models import GoodsInfo, MemberActivityInfo, ShotTypeInfo, RightInfo
    6
    +from utils.redis.rshot import update_shot_member_data
    7
    +
    8
    +
    9
    +class GoodsInfoAdmin(admin.ModelAdmin):
    10
    +    list_display = ('good_id', 'good_type', 'title', 'desc', 'image', 'is_slider', 'slider_image', 'integral', 'fee', 'minlevel', 'position', 'status', 'created_at', 'updated_at')
    11
    +    list_filter = ('is_slider', 'status')
    12
    +
    13
    +
    14
    +class RightInfoAdmin(admin.ModelAdmin):
    15
    +    list_display = ('right_id', 'icon', 'title', 'subtitle', 'detail', 'minlevel', 'position', 'status', 'created_at', 'updated_at')
    16
    +
    17
    +
    18
    +class ShotTypeInfoAdmin(admin.ModelAdmin):
    19
    +    list_display = ('shot_type_id', 'shot_type_name', 'position', 'status', 'created_at', 'updated_at')
    20
    +
    21
    +    def save_model(self, request, obj, form, change):
    22
    +        obj.save()
    23
    +        update_shot_member_data()
    24
    +
    25
    +    def delete_model(self, request, obj):
    26
    +        obj.delete()
    27
    +        update_shot_member_data()
    28
    +
    29
    +
    30
    +class MemberActivityInfoAdmin(admin.ModelAdmin):
    31
    +    list_display = ('title', 'subtitle', 'date', 'location', 'image', 'is_slider', 'slider_image', 'position', 'status', 'created_at', 'updated_at')
    32
    +    list_filter = ('is_slider', 'status')
    33
    +
    34
    +
    35
    +admin.site.register(GoodsInfo, GoodsInfoAdmin)
    36
    +admin.site.register(RightInfo, RightInfoAdmin)
    37
    +admin.site.register(ShotTypeInfo, ShotTypeInfoAdmin)
    38
    +admin.site.register(MemberActivityInfo, MemberActivityInfoAdmin)

    + 8 - 0
    member/apps.py

    @@ -0,0 +1,8 @@
    1
    +# -*- coding: utf-8 -*-
    2
    +from __future__ import unicode_literals
    3
    +
    4
    +from django.apps import AppConfig
    5
    +
    6
    +
    7
    +class MemberConfig(AppConfig):
    8
    +    name = 'member'

    + 104 - 0
    member/migrations/0001_initial.py

    @@ -0,0 +1,104 @@
    1
    +# -*- coding: utf-8 -*-
    2
    +# Generated by Django 1.11.26 on 2019-11-19 05:48
    3
    +from __future__ import unicode_literals
    4
    +
    5
    +from django.db import migrations, models
    6
    +import django_models_ext.fileext
    7
    +import shortuuidfield.fields
    8
    +import simditor.fields
    9
    +
    10
    +
    11
    +class Migration(migrations.Migration):
    12
    +
    13
    +    initial = True
    14
    +
    15
    +    dependencies = [
    16
    +    ]
    17
    +
    18
    +    operations = [
    19
    +        migrations.CreateModel(
    20
    +            name='GoodsInfo',
    21
    +            fields=[
    22
    +                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
    23
    +                ('status', models.BooleanField(db_index=True, default=True, help_text='Status', verbose_name='status')),
    24
    +                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')),
    25
    +                ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')),
    26
    +                ('good_id', shortuuidfield.fields.ShortUUIDField(blank=True, db_index=True, editable=False, help_text='\u5546\u54c1\u552f\u4e00\u6807\u8bc6', max_length=22, null=True, unique=True)),
    27
    +                ('good_type', models.IntegerField(choices=[(0, '\u5b9e\u7269'), (1, '\u865a\u62df')], db_index=True, default=1, help_text='\u5546\u54c1\u7c7b\u578b', verbose_name='good_type')),
    28
    +                ('title', models.CharField(blank=True, help_text='\u5546\u54c1\u540d\u79f0', max_length=255, null=True, verbose_name='title')),
    29
    +                ('desc', simditor.fields.RichTextField(blank=True, help_text='\u5546\u54c1\u63cf\u8ff0', null=True, verbose_name='desc')),
    30
    +                ('image', models.ImageField(blank=True, help_text='\u5546\u54c1\u56fe\u7247', null=True, upload_to=django_models_ext.fileext.upload_path, verbose_name='image')),
    31
    +                ('is_slider', models.BooleanField(db_index=True, default=True, help_text='\u662f\u5426\u4e3a\u8f6e\u64ad\u5546\u54c1', verbose_name='is_slider')),
    32
    +                ('slider_image', models.ImageField(blank=True, help_text='\u5546\u54c1\u8f6e\u64ad\u56fe\u7247', null=True, upload_to=django_models_ext.fileext.upload_path, verbose_name='slider_image')),
    33
    +                ('integral', models.IntegerField(default=99999, help_text='\u5151\u6362\u6240\u9700\u79ef\u5206', verbose_name='integral')),
    34
    +                ('fee', models.IntegerField(default=99999, help_text='\u5151\u6362\u9700\u989d\u5916\u652f\u4ed8\u91d1\u989d\uff0c\u5355\u4f4d\u5206', verbose_name='fee')),
    35
    +                ('minlevel', models.IntegerField(default=0, help_text='\u5151\u6362\u6700\u4f4e\u4f1a\u5458\u7ea7\u522b', verbose_name='minlevel')),
    36
    +                ('position', models.IntegerField(db_index=True, default=1, help_text='\u6392\u5e8f', verbose_name='position')),
    37
    +            ],
    38
    +            options={
    39
    +                'verbose_name': '\u5546\u54c1\u4fe1\u606f',
    40
    +                'verbose_name_plural': '\u5546\u54c1\u4fe1\u606f',
    41
    +            },
    42
    +        ),
    43
    +        migrations.CreateModel(
    44
    +            name='MemberActivityInfo',
    45
    +            fields=[
    46
    +                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
    47
    +                ('status', models.BooleanField(db_index=True, default=True, help_text='Status', verbose_name='status')),
    48
    +                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')),
    49
    +                ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')),
    50
    +                ('title', models.CharField(blank=True, help_text='\u6d3b\u52a8\u540d\u79f0', max_length=255, null=True, verbose_name='title')),
    51
    +                ('subtitle', models.CharField(blank=True, help_text='\u6d3b\u52a8\u4e8c\u7ea7\u540d\u79f0', max_length=255, null=True, verbose_name='subtitle')),
    52
    +                ('date', models.DateField(blank=True, help_text='\u6d3b\u52a8\u65f6\u95f4', null=True, verbose_name='date')),
    53
    +                ('location', models.CharField(blank=True, help_text='\u6d3b\u52a8\u5730\u70b9', max_length=255, null=True, verbose_name='location')),
    54
    +                ('image', models.ImageField(blank=True, help_text='\u6d3b\u52a8\u5185\u5bb9\u56fe\u7247', null=True, upload_to=django_models_ext.fileext.upload_path, verbose_name='image')),
    55
    +                ('cover', models.ImageField(blank=True, help_text='\u6d3b\u52a8\u5217\u8868\u56fe\u7247', null=True, upload_to=django_models_ext.fileext.upload_path, verbose_name='cover')),
    56
    +                ('is_slider', models.BooleanField(db_index=True, default=True, help_text='\u662f\u5426\u4e3a\u8f6e\u64ad\u6d3b\u52a8', verbose_name='is_slider')),
    57
    +                ('slider_image', models.ImageField(blank=True, help_text='\u6d3b\u52a8\u8f6e\u64ad\u56fe\u7247', null=True, upload_to=django_models_ext.fileext.upload_path, verbose_name='slider_image')),
    58
    +                ('content_rich_text', simditor.fields.RichTextField(blank=True, help_text='\u6d3b\u52a8\u63cf\u8ff0', null=True, verbose_name='content_rich_text')),
    59
    +                ('share_img_link', models.CharField(blank=True, help_text='\u6d3b\u52a8\u56fe\u7247\u5206\u4eab', max_length=255, null=True, verbose_name='share_img_link')),
    60
    +                ('share_h5_link', models.CharField(blank=True, help_text='\u6d3b\u52a8H5\u5206\u4eab', max_length=255, null=True, verbose_name='share_h5_link')),
    61
    +                ('position', models.IntegerField(db_index=True, default=1, help_text='\u6392\u5e8f', verbose_name='position')),
    62
    +            ],
    63
    +            options={
    64
    +                'verbose_name': '\u4f1a\u5458\u6d3b\u52a8\u4fe1\u606f',
    65
    +                'verbose_name_plural': '\u4f1a\u5458\u6d3b\u52a8\u4fe1\u606f',
    66
    +            },
    67
    +        ),
    68
    +        migrations.CreateModel(
    69
    +            name='RightInfo',
    70
    +            fields=[
    71
    +                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
    72
    +                ('status', models.BooleanField(db_index=True, default=True, help_text='Status', verbose_name='status')),
    73
    +                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')),
    74
    +                ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')),
    75
    +                ('right_id', shortuuidfield.fields.ShortUUIDField(blank=True, db_index=True, editable=False, help_text='\u6743\u76ca\u552f\u4e00\u6807\u8bc6', max_length=22, null=True, unique=True)),
    76
    +                ('icon', models.ImageField(blank=True, help_text='\u6743\u76ca\u56fe\u6807', null=True, upload_to=django_models_ext.fileext.upload_path, verbose_name='icon')),
    77
    +                ('title', models.CharField(blank=True, help_text='\u6743\u76ca\u540d\u79f0', max_length=255, null=True, verbose_name='title')),
    78
    +                ('subtitle', models.CharField(blank=True, help_text='\u6743\u76ca\u4e8c\u7ea7\u540d\u79f0', max_length=255, null=True, verbose_name='subtitle')),
    79
    +                ('detail', simditor.fields.RichTextField(blank=True, help_text='\u6743\u76ca\u8be6\u60c5', null=True, verbose_name='detail')),
    80
    +                ('minlevel', models.IntegerField(default=0, help_text='\u6743\u76ca\u6700\u4f4e\u4f1a\u5458\u7ea7\u522b', verbose_name='minlevel')),
    81
    +                ('position', models.IntegerField(db_index=True, default=1, help_text='\u6392\u5e8f', verbose_name='position')),
    82
    +            ],
    83
    +            options={
    84
    +                'verbose_name': '\u6743\u76ca\u4fe1\u606f',
    85
    +                'verbose_name_plural': '\u6743\u76ca\u4fe1\u606f',
    86
    +            },
    87
    +        ),
    88
    +        migrations.CreateModel(
    89
    +            name='ShotTypeInfo',
    90
    +            fields=[
    91
    +                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
    92
    +                ('status', models.BooleanField(db_index=True, default=True, help_text='Status', verbose_name='status')),
    93
    +                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')),
    94
    +                ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')),
    95
    +                ('shot_type_id', shortuuidfield.fields.ShortUUIDField(blank=True, db_index=True, editable=False, help_text='\u955c\u5934\u7c7b\u578b\u552f\u4e00\u6807\u8bc6', max_length=22, null=True, unique=True)),
    96
    +                ('shot_type_name', models.CharField(blank=True, help_text='\u955c\u5934\u7c7b\u578b\u540d\u79f0', max_length=255, null=True, verbose_name='shot_type_name')),
    97
    +                ('position', models.IntegerField(db_index=True, default=1, help_text='\u6392\u5e8f', verbose_name='position')),
    98
    +            ],
    99
    +            options={
    100
    +                'verbose_name': '\u955c\u5934\u7c7b\u578b\u4fe1\u606f',
    101
    +                'verbose_name_plural': '\u955c\u5934\u7c7b\u578b\u4fe1\u606f',
    102
    +            },
    103
    +        ),
    104
    +    ]

    + 0 - 0
    member/migrations/__init__.py


    + 211 - 0
    member/models.py

    @@ -0,0 +1,211 @@
    1
    +# -*- coding: utf-8 -*-
    2
    +
    3
    +from django.db import models
    4
    +from django.utils.translation import ugettext_lazy as _
    5
    +from django_models_ext import BaseModelMixin, upload_file_path, upload_file_url, upload_path
    6
    +from simditor.fields import RichTextField
    7
    +from shortuuidfield import ShortUUIDField
    8
    +
    9
    +from mch.models import ModelInfo
    10
    +
    11
    +
    12
    +class GoodsInfo(BaseModelMixin):
    13
    +    PHYSICAL = 0
    14
    +    VIRTUAL = 1
    15
    +
    16
    +    GOOD_TYPE_TUPLE = (
    17
    +        (PHYSICAL, u'实物'),
    18
    +        (VIRTUAL, u'虚拟'),
    19
    +    )
    20
    +
    21
    +    good_id = ShortUUIDField(_(u'good_id'), max_length=32, blank=True, null=True, help_text=u'商品唯一标识', db_index=True, unique=True)
    22
    +    good_type = models.IntegerField(_(u'good_type'), choices=GOOD_TYPE_TUPLE, default=VIRTUAL, help_text=u'商品类型', db_index=True)
    23
    +
    24
    +    title = models.CharField(_(u'title'), max_length=255, blank=True, null=True, help_text=u'商品名称')
    25
    +    desc = RichTextField(_(u'desc'), blank=True, null=True, help_text=u'商品描述')
    26
    +
    27
    +    image = models.ImageField(_(u'image'), upload_to=upload_path, blank=True, null=True, help_text=u'商品图片')
    28
    +
    29
    +    is_slider = models.BooleanField(_(u'is_slider'), default=True, help_text=_(u'是否为轮播商品'), db_index=True)
    30
    +    slider_image = models.ImageField(_(u'slider_image'), upload_to=upload_path, blank=True, null=True, help_text=u'商品轮播图片')
    31
    +
    32
    +    integral = models.IntegerField(_(u'integral'), default=99999, help_text=u'兑换所需积分')
    33
    +    fee = models.IntegerField(_(u'fee'), default=99999, help_text=u'兑换需额外支付金额,单位分')
    34
    +
    35
    +    minlevel = models.IntegerField(_(u'minlevel'), default=0, help_text=u'兑换最低会员级别')
    36
    +
    37
    +    position = models.IntegerField(_(u'position'), default=1, help_text=u'排序', db_index=True)
    38
    +
    39
    +    class Meta:
    40
    +        verbose_name = _(u'会员商品信息')
    41
    +        verbose_name_plural = _(u'会员商品信息')
    42
    +
    43
    +    def __unicode__(self):
    44
    +        return unicode(self.pk)
    45
    +
    46
    +    @property
    47
    +    def image_path(self):
    48
    +        return upload_file_path(self.image)
    49
    +
    50
    +    @property
    51
    +    def image_url(self):
    52
    +        return upload_file_url(self.image)
    53
    +
    54
    +    @property
    55
    +    def slider_image_path(self):
    56
    +        return upload_file_path(self.slider_image)
    57
    +
    58
    +    @property
    59
    +    def slider_image_url(self):
    60
    +        return upload_file_url(self.slider_image)
    61
    +
    62
    +    @property
    63
    +    def data(self):
    64
    +        return {
    65
    +            'good_id': self.good_id,
    66
    +            'good_type': self.good_type,
    67
    +            'title': self.title,
    68
    +            'desc': self.desc,
    69
    +            'image': self.image_url,
    70
    +            'slider_image': self.slider_image_url,
    71
    +            'integral': self.integral,
    72
    +            'fee': self.fee,
    73
    +            'minlevel': self.minlevel,
    74
    +            'able': True,
    75
    +        }
    76
    +
    77
    +
    78
    +class RightInfo(BaseModelMixin):
    79
    +    right_id = ShortUUIDField(_(u'right_id'), max_length=32, blank=True, null=True, help_text=u'权益唯一标识', db_index=True, unique=True)
    80
    +
    81
    +    icon = models.ImageField(_(u'icon'), upload_to=upload_path, blank=True, null=True, help_text=u'权益图标')
    82
    +    title = models.CharField(_(u'title'), max_length=255, blank=True, null=True, help_text=u'权益名称')
    83
    +    subtitle = models.CharField(_(u'subtitle'), max_length=255, blank=True, null=True, help_text=u'权益二级名称')
    84
    +    detail = RichTextField(_(u'detail'), blank=True, null=True, help_text=u'权益详情')
    85
    +
    86
    +    minlevel = models.IntegerField(_(u'minlevel'), default=0, help_text=u'权益最低会员级别')
    87
    +
    88
    +    position = models.IntegerField(_(u'position'), default=1, help_text=u'排序', db_index=True)
    89
    +
    90
    +    class Meta:
    91
    +        verbose_name = _(u'会员权益信息')
    92
    +        verbose_name_plural = _(u'会员权益信息')
    93
    +
    94
    +    def __unicode__(self):
    95
    +        return unicode(self.pk)
    96
    +
    97
    +    @property
    98
    +    def icon_path(self):
    99
    +        return upload_file_path(self.icon)
    100
    +
    101
    +    @property
    102
    +    def icon_url(self):
    103
    +        return upload_file_url(self.icon)
    104
    +
    105
    +    @property
    106
    +    def data(self):
    107
    +        return {
    108
    +            'right_id': self.right_id,
    109
    +            'icon': self.icon_url,
    110
    +            'title': self.title,
    111
    +            'subtitle': self.subtitle,
    112
    +            'detail': self.detail,
    113
    +            'minlevel': self.minlevel,
    114
    +            "able": True,
    115
    +            "left_num": 3,
    116
    +            "left_tip": 3,
    117
    +        }
    118
    +
    119
    +
    120
    +class ShotTypeInfo(BaseModelMixin):
    121
    +    shot_type_id = ShortUUIDField(_(u'shot_type_id'), max_length=32, blank=True, null=True, help_text=u'镜头类型唯一标识', db_index=True, unique=True)
    122
    +    shot_type_name = models.CharField(_(u'shot_type_name'), max_length=255, blank=True, null=True, help_text=u'镜头类型名称')
    123
    +
    124
    +    position = models.IntegerField(_(u'position'), default=1, help_text=u'排序', db_index=True)
    125
    +
    126
    +    class Meta:
    127
    +        verbose_name = _(u'镜头类型信息')
    128
    +        verbose_name_plural = _(u'镜头类型信息')
    129
    +
    130
    +    def __unicode__(self):
    131
    +        return unicode(self.pk)
    132
    +
    133
    +    @property
    134
    +    def shots(self):
    135
    +        models = ModelInfo.objects.filter(shot_type_id=self.shot_type_id, status=True)
    136
    +        return [model.shot_data for model in models]
    137
    +
    138
    +    @property
    139
    +    def data(self):
    140
    +        return {
    141
    +            'type_id': self.shot_type_id,
    142
    +            'type_name': self.shot_type_name,
    143
    +            'shots': self.shots,
    144
    +        }
    145
    +
    146
    +
    147
    +class MemberActivityInfo(BaseModelMixin):
    148
    +    title = models.CharField(_(u'title'), max_length=255, blank=True, null=True, help_text=u'活动名称')
    149
    +    subtitle = models.CharField(_(u'subtitle'), max_length=255, blank=True, null=True, help_text=u'活动二级名称')
    150
    +
    151
    +    date = models.DateField(_(u'date'), blank=True, null=True, help_text=u'活动时间')
    152
    +    location = models.CharField(_(u'location'), max_length=255, blank=True, null=True, help_text=u'活动地点')
    153
    +
    154
    +    image = models.ImageField(_(u'image'), upload_to=upload_path, blank=True, null=True, help_text=u'活动内容图片')
    155
    +
    156
    +    cover = models.ImageField(_(u'cover'), upload_to=upload_path, blank=True, null=True, help_text=u'活动列表图片')
    157
    +
    158
    +    is_slider = models.BooleanField(_(u'is_slider'), default=True, help_text=_(u'是否为轮播活动'), db_index=True)
    159
    +    slider_image = models.ImageField(_(u'slider_image'), upload_to=upload_path, blank=True, null=True, help_text=u'活动轮播图片')
    160
    +
    161
    +    content_rich_text = RichTextField(_(u'content_rich_text'), blank=True, null=True, help_text=u'活动描述')
    162
    +
    163
    +    share_img_link = models.CharField(_(u'share_img_link'), max_length=255, blank=True, null=True, help_text=u'活动图片分享')
    164
    +    share_h5_link = models.CharField(_(u'share_h5_link'), max_length=255, blank=True, null=True, help_text=u'活动H5分享')
    165
    +
    166
    +    position = models.IntegerField(_(u'position'), default=1, help_text=u'排序', db_index=True)
    167
    +
    168
    +    class Meta:
    169
    +        verbose_name = _(u'会员活动信息')
    170
    +        verbose_name_plural = _(u'会员活动信息')
    171
    +
    172
    +    def __unicode__(self):
    173
    +        return unicode(self.pk)
    174
    +
    175
    +    @property
    176
    +    def image_path(self):
    177
    +        return upload_file_path(self.image)
    178
    +
    179
    +    @property
    180
    +    def image_url(self):
    181
    +        return upload_file_url(self.image)
    182
    +
    183
    +    @property
    184
    +    def cover_path(self):
    185
    +        return upload_file_path(self.cover)
    186
    +
    187
    +    @property
    188
    +    def cover_url(self):
    189
    +        return upload_file_url(self.cover)
    190
    +
    191
    +    @property
    192
    +    def slider_image_path(self):
    193
    +        return upload_file_path(self.slider_image)
    194
    +
    195
    +    @property
    196
    +    def slider_image_url(self):
    197
    +        return upload_file_url(self.slider_image)
    198
    +
    199
    +    @property
    200
    +    def data(self):
    201
    +        return {
    202
    +            'id': self.pk,
    203
    +            'title': self.title,
    204
    +            'subtitle': self.subtitle,
    205
    +            'date': self.date,
    206
    +            'location': self.location,
    207
    +            'cover_url': self.cover_url,
    208
    +            'content_rich_text': self.content_rich_text,
    209
    +            'state': 0,
    210
    +            'is_signed': 0,
    211
    +        }

    + 7 - 0
    member/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
    member/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.

    + 1 - 1
    pre/views.py

    @@ -2,11 +2,11 @@
    2 2
     
    3 3
     from __future__ import division
    4 4
     
    5
    +import xlrd
    5 6
     from django.conf import settings
    6 7
     from pysnippets.strsnippets import strip
    7 8
     from TimeConvert import TimeConvert as tc
    8 9
     
    9
    -import xlrd
    10 10
     from mch.models import BrandInfo, ConsumeInfoSubmitLogInfo, DistributorInfo, ModelInfo
    11 11
     from statistic.models import (ConsumeDistributorSaleStatisticInfo, ConsumeModelSaleStatisticInfo,
    12 12
                                   ConsumeProvinceSaleStatisticInfo, ConsumeSaleStatisticInfo, ConsumeUserStatisticInfo,

    + 4 - 4
    requirements.txt

    @@ -1,15 +1,15 @@
    1 1
     CodeConvert==2.0.5
    2
    -MySQL-python==1.2.5
    3 2
     Pillow==5.0.0
    4 3
     StatusCode==1.0.0
    5 4
     TimeConvert==1.5.0
    6
    -furl==2.0.0
    5
    +furl==2.1.0
    7 6
     isoweek==1.3.3
    8 7
     jsonfield==2.0.2
    9 8
     mock==2.0.0
    10 9
     monetary==1.0.3
    11
    -pysnippets==1.0.8
    12
    -qiniu==7.2.2
    10
    +mysqlclient==1.4.5
    11
    +pysnippets==1.1.2
    12
    +qiniu==7.2.6
    13 13
     requests==2.21.0
    14 14
     rlog==0.3
    15 15
     rsa==3.4.2

    + 6 - 6
    requirements_dj.txt

    @@ -1,20 +1,20 @@
    1
    -Django==1.11.25
    1
    +Django==1.11.26
    2 2
     django-admin==2.0.0
    3
    -django-cors-headers==2.4.0
    3
    +django-cors-headers==3.0.2
    4 4
     django-curtail-uuid==1.0.4
    5
    -django-detect==1.0.8
    5
    +django-detect==1.0.16
    6 6
     django-file-md5==1.0.3
    7 7
     django-file-upload==1.1.1
    8 8
     django-ip==1.0.2
    9
    -django-json-render==1.0.2
    9
    +django-json-render==1.0.3
    10 10
     django-json-response==1.1.5
    11 11
     django-logit==1.1.3
    12 12
     django-mobi==0.1.7
    13 13
     django-models-ext==1.1.9
    14 14
     django-multidomain==1.1.4
    15 15
     django-paginator2==1.1.3
    16
    -django-query==1.0.3
    17
    -django-redis-connector==1.0.1
    16
    +django-query==1.0.6
    17
    +django-redis-connector==1.0.3
    18 18
     django-response==1.1.1
    19 19
     django-rlog==1.0.7
    20 20
     django-shortuuidfield==0.1.3

    + 1 - 1
    requirements_pywe.txt

    @@ -4,7 +4,7 @@ pywe-jssdk==1.1.0
    4 4
     pywe-membercard==1.0.1
    5 5
     pywe-miniapp==1.1.5
    6 6
     pywe-oauth==1.0.7
    7
    -pywe-pay==1.0.12
    7
    +pywe-pay==1.0.13
    8 8
     pywe-pay-notify==1.0.4
    9 9
     pywe-response==1.0.1
    10 10
     pywe-sign==1.1.0

    + 1 - 1
    requirements_redis.txt

    @@ -1,3 +1,3 @@
    1
    -hiredis==1.0.0
    1
    +hiredis==1.0.1
    2 2
     redis==2.10.6
    3 3
     redis-extensions==1.2.5

    + 0 - 0
    simditor/__init__.py


    + 36 - 0
    simditor/fields.py

    @@ -0,0 +1,36 @@
    1
    +# -- coding: utf-8 --
    2
    +"""simditor fields."""
    3
    +from django import forms
    4
    +from django.db import models
    5
    +
    6
    +from .widgets import SimditorWidget
    7
    +
    8
    +
    9
    +class RichTextFormField(forms.fields.CharField):
    10
    +    """RichTextFormField."""
    11
    +
    12
    +    def __init__(self, *args, **kwargs):
    13
    +        kwargs.update(
    14
    +            {
    15
    +                'widget': SimditorWidget()
    16
    +            }
    17
    +        )
    18
    +        super(RichTextFormField, self).__init__(*args, **kwargs)
    19
    +
    20
    +
    21
    +class RichTextField(models.TextField):
    22
    +    """RichTextField."""
    23
    +
    24
    +    def __init__(self, *args, **kwargs):
    25
    +        super(RichTextField, self).__init__(*args, **kwargs)
    26
    +
    27
    +    def formfield(self, **kwargs):
    28
    +        defaults = {
    29
    +            'form_class': self._get_form_class()
    30
    +        }
    31
    +        defaults.update(kwargs)
    32
    +        return super(RichTextField, self).formfield(**defaults)
    33
    +
    34
    +    @staticmethod
    35
    +    def _get_form_class():
    36
    +        return RichTextFormField

    + 0 - 0
    simditor/image/__init__.py


    + 11 - 0
    simditor/image/dummy_backend.py

    @@ -0,0 +1,11 @@
    1
    +# -- coding: utf-8 --
    2
    +"""simditor image pillow_backend."""
    3
    +from __future__ import absolute_import
    4
    +
    5
    +from simditor import utils
    6
    +
    7
    +
    8
    +def image_verify(file_object):
    9
    +    """image_verify."""
    10
    +    if not utils.is_valid_image_extension(file_object.name):
    11
    +        raise utils.NotAnImageException

    + 28 - 0
    simditor/image/pillow_backend.py

    @@ -0,0 +1,28 @@
    1
    +# -- coding: utf-8 --
    2
    +"""simditor image pillow_backend."""
    3
    +from __future__ import absolute_import
    4
    +
    5
    +import os
    6
    +from io import BytesIO
    7
    +
    8
    +from django.core.files.storage import default_storage
    9
    +from django.core.files.uploadedfile import InMemoryUploadedFile
    10
    +
    11
    +from simditor import utils
    12
    +
    13
    +
    14
    +try:
    15
    +    from PIL import Image, ImageOps
    16
    +except ImportError:
    17
    +    import Image
    18
    +    import ImageOps
    19
    +
    20
    +
    21
    +THUMBNAIL_SIZE = (75, 75)
    22
    +
    23
    +
    24
    +def image_verify(f):
    25
    +    try:
    26
    +        Image.open(f).verify()
    27
    +    except IOError:
    28
    +        raise utils.NotAnImageException

    + 16 - 0
    simditor/image_processing.py

    @@ -0,0 +1,16 @@
    1
    +# -- coding: utf-8 --
    2
    +"""simditor image_processing."""
    3
    +from __future__ import absolute_import
    4
    +
    5
    +from django.conf import settings
    6
    +
    7
    +
    8
    +def get_backend():
    9
    +    """Get backend."""
    10
    +    backend = getattr(settings, 'SIMDITOR_IMAGE_BACKEND', None)
    11
    +
    12
    +    if backend == 'pillow':
    13
    +        from simditor.image import pillow_backend as backend
    14
    +    else:
    15
    +        from simditor.image import dummy_backend as backend
    16
    +    return backend

    BIN
    simditor/static/simditor/fonts/icomoon.eot


    + 11 - 0
    simditor/static/simditor/fonts/icomoon.svg

    @@ -0,0 +1,11 @@
    1
    +<?xml version="1.0" standalone="no"?>
    2
    +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
    3
    +<svg xmlns="http://www.w3.org/2000/svg">
    4
    +<metadata>Generated by IcoMoon</metadata>
    5
    +<defs>
    6
    +<font id="icomoon" horiz-adv-x="512">
    7
    +<font-face units-per-em="512" ascent="480" descent="-32" />
    8
    +<missing-glyph horiz-adv-x="512" />
    9
    +<glyph unicode="&#x20;" d="" horiz-adv-x="256" />
    10
    +<glyph unicode="&#xe600;" d="M438.624 86.624l-73.376 73.376-45.248-45.248 73.376-73.376-73.376-73.376h192v192zM192 480h-192v-192l73.376 73.376 72.688-72.624 45.248 45.248-72.688 72.624zM192 114.752l-45.248 45.248-73.376-73.376-73.376 73.376v-192h192l-73.376 73.376zM512 480h-192l73.376-73.376-72.688-72.624 45.248-45.248 72.688 72.624 73.376-73.376z" />
    11
    +</font></defs></svg>

    BIN
    simditor/static/simditor/fonts/icomoon.ttf


    BIN
    simditor/static/simditor/fonts/icomoon.woff


    + 82 - 0
    simditor/static/simditor/fonts/selection.json

    @@ -0,0 +1,82 @@
    1
    +{
    2
    +	"IcoMoonType": "selection",
    3
    +	"icons": [
    4
    +		{
    5
    +			"icon": {
    6
    +				"paths": [
    7
    +					"M877.248 786.752l-146.752-146.752-90.496 90.496 146.752 146.752-146.752 146.752h384v-384zM384 0h-384v384l146.752-146.752 145.376 145.248 90.496-90.496-145.376-145.248zM384 730.496l-90.496-90.496-146.752 146.752-146.752-146.752v384h384l-146.752-146.752zM1024 0h-384l146.752 146.752-145.376 145.248 90.496 90.496 145.376-145.248 146.752 146.752z"
    8
    +				],
    9
    +				"tags": [
    10
    +					"fullscreen",
    11
    +					"expand"
    12
    +				],
    13
    +				"grid": 16,
    14
    +				"attrs": []
    15
    +			},
    16
    +			"attrs": [],
    17
    +			"properties": {
    18
    +				"id": 99,
    19
    +				"order": 2,
    20
    +				"prevSize": 16,
    21
    +				"code": 58880,
    22
    +				"name": "fullscreen"
    23
    +			},
    24
    +			"setIdx": 1,
    25
    +			"setId": 6,
    26
    +			"iconIdx": 99
    27
    +		}
    28
    +	],
    29
    +	"height": 1024,
    30
    +	"metadata": {
    31
    +		"name": "icomoon"
    32
    +	},
    33
    +	"preferences": {
    34
    +		"fontPref": {
    35
    +			"prefix": "icon-",
    36
    +			"metadata": {
    37
    +				"fontFamily": "icomoon",
    38
    +				"majorVersion": 1,
    39
    +				"minorVersion": 0
    40
    +			},
    41
    +			"showGlyphs": true,
    42
    +			"metrics": {
    43
    +				"emSize": 512,
    44
    +				"baseline": 6.25,
    45
    +				"whitespace": 50
    46
    +			},
    47
    +			"resetPoint": 58880,
    48
    +			"showQuickUse": true,
    49
    +			"quickUsageToken": false,
    50
    +			"showMetrics": false,
    51
    +			"showMetadata": false,
    52
    +			"autoHost": true,
    53
    +			"embed": false,
    54
    +			"ie7": false,
    55
    +			"showSelector": false,
    56
    +			"showVersion": true
    57
    +		},
    58
    +		"imagePref": {
    59
    +			"color": 0,
    60
    +			"height": 32,
    61
    +			"columns": 16,
    62
    +			"margin": 16,
    63
    +			"png": false,
    64
    +			"sprites": true,
    65
    +			"prefix": "icon-"
    66
    +		},
    67
    +		"historySize": 100,
    68
    +		"showCodes": true,
    69
    +		"gridSize": 16,
    70
    +		"showLiga": false,
    71
    +		"showGrid": true,
    72
    +		"showGlyphs": true,
    73
    +		"showQuickUse": true,
    74
    +		"search": "",
    75
    +		"quickUsageToken": {
    76
    +			"UntitledProject1": "ZWEwOTk2NTRmNjMyOGQ1MzAwZWFiYmJlODViMWMzZDcjMiMxNDA3NzM0MTA2IyMj"
    77
    +		},
    78
    +		"showQuickUse2": true,
    79
    +		"showSVGs": true,
    80
    +		"fontHostingName": false
    81
    +	}
    82
    +}

    BIN
    simditor/static/simditor/images/emoji/+1.png


    BIN
    simditor/static/simditor/images/emoji/-1.png


    BIN
    simditor/static/simditor/images/emoji/100.png


    BIN
    simditor/static/simditor/images/emoji/109.png


    BIN
    simditor/static/simditor/images/emoji/1234.png


    BIN
    simditor/static/simditor/images/emoji/a.png


    BIN
    simditor/static/simditor/images/emoji/ab.png


    BIN
    simditor/static/simditor/images/emoji/abc.png


    BIN
    simditor/static/simditor/images/emoji/abcd.png


    BIN
    simditor/static/simditor/images/emoji/accept.png


    BIN
    simditor/static/simditor/images/emoji/aerial_tramway.png


    BIN
    simditor/static/simditor/images/emoji/airplane.png


    BIN
    simditor/static/simditor/images/emoji/alarm_clock.png


    BIN
    simditor/static/simditor/images/emoji/alien.png


    BIN
    simditor/static/simditor/images/emoji/ambulance.png


    BIN
    simditor/static/simditor/images/emoji/anchor.png


    BIN
    simditor/static/simditor/images/emoji/angel.png


    BIN
    simditor/static/simditor/images/emoji/anger.png


    BIN
    simditor/static/simditor/images/emoji/angry.png


    BIN
    simditor/static/simditor/images/emoji/anguished.png


    BIN
    simditor/static/simditor/images/emoji/ant.png


    BIN
    simditor/static/simditor/images/emoji/apple.png


    BIN
    simditor/static/simditor/images/emoji/aquarius.png


    BIN
    simditor/static/simditor/images/emoji/aries.png


    BIN
    simditor/static/simditor/images/emoji/arrow_backward.png


    BIN
    simditor/static/simditor/images/emoji/arrow_double_down.png


    BIN
    simditor/static/simditor/images/emoji/arrow_double_up.png


    BIN
    simditor/static/simditor/images/emoji/arrow_down.png


    BIN
    simditor/static/simditor/images/emoji/arrow_down_small.png


    BIN
    simditor/static/simditor/images/emoji/arrow_forward.png


    BIN
    simditor/static/simditor/images/emoji/arrow_heading_down.png


    BIN
    simditor/static/simditor/images/emoji/arrow_heading_up.png


    BIN
    simditor/static/simditor/images/emoji/arrow_left.png


    BIN
    simditor/static/simditor/images/emoji/arrow_lower_left.png


    BIN
    simditor/static/simditor/images/emoji/arrow_lower_right.png


    BIN
    simditor/static/simditor/images/emoji/arrow_right.png


    BIN
    simditor/static/simditor/images/emoji/arrow_right_hook.png


    BIN
    simditor/static/simditor/images/emoji/arrow_up.png


    BIN
    simditor/static/simditor/images/emoji/arrow_up_down.png


    BIN
    simditor/static/simditor/images/emoji/arrow_up_small.png


    BIN
    simditor/static/simditor/images/emoji/arrow_upper_left.png


    BIN
    simditor/static/simditor/images/emoji/arrow_upper_right.png


    BIN
    simditor/static/simditor/images/emoji/arrows_clockwise.png


    BIN
    simditor/static/simditor/images/emoji/arrows_counterclockwise.png


    BIN
    simditor/static/simditor/images/emoji/art.png


    BIN
    simditor/static/simditor/images/emoji/articulated_lorry.png


    BIN
    simditor/static/simditor/images/emoji/astonished.png


    BIN
    simditor/static/simditor/images/emoji/atm.png


    BIN
    simditor/static/simditor/images/emoji/b.png


    BIN
    simditor/static/simditor/images/emoji/baby.png


    BIN
    simditor/static/simditor/images/emoji/baby_bottle.png


    BIN
    simditor/static/simditor/images/emoji/baby_chick.png


    BIN
    simditor/static/simditor/images/emoji/baby_symbol.png


    BIN
    simditor/static/simditor/images/emoji/baggage_claim.png


    BIN
    simditor/static/simditor/images/emoji/balloon.png


    BIN
    simditor/static/simditor/images/emoji/ballot_box_with_check.png


    BIN
    simditor/static/simditor/images/emoji/bamboo.png


    BIN
    simditor/static/simditor/images/emoji/banana.png


    BIN
    simditor/static/simditor/images/emoji/bangbang.png


    BIN
    simditor/static/simditor/images/emoji/bank.png


    BIN
    simditor/static/simditor/images/emoji/bar_chart.png


    BIN
    simditor/static/simditor/images/emoji/barber.png


    BIN
    simditor/static/simditor/images/emoji/baseball.png


    BIN
    simditor/static/simditor/images/emoji/basketball.png


    BIN
    simditor/static/simditor/images/emoji/bath.png


    BIN
    simditor/static/simditor/images/emoji/bathtub.png


    BIN
    simditor/static/simditor/images/emoji/battery.png


    BIN
    simditor/static/simditor/images/emoji/bear.png


    BIN
    simditor/static/simditor/images/emoji/beer.png


    BIN
    simditor/static/simditor/images/emoji/beers.png


    BIN
    simditor/static/simditor/images/emoji/beetle.png


    BIN
    simditor/static/simditor/images/emoji/beginner.png


    BIN
    simditor/static/simditor/images/emoji/bell.png


    BIN
    simditor/static/simditor/images/emoji/bento.png


    BIN
    simditor/static/simditor/images/emoji/bicyclist.png


    BIN
    simditor/static/simditor/images/emoji/bike.png


    BIN
    simditor/static/simditor/images/emoji/bikini.png


    BIN
    simditor/static/simditor/images/emoji/bird.png


    BIN
    simditor/static/simditor/images/emoji/birthday.png


    BIN
    simditor/static/simditor/images/emoji/black_circle.png


    BIN
    simditor/static/simditor/images/emoji/black_joker.png


    BIN
    simditor/static/simditor/images/emoji/black_nib.png


    BIN
    simditor/static/simditor/images/emoji/black_square.png


    BIN
    simditor/static/simditor/images/emoji/black_square_button.png


    BIN
    simditor/static/simditor/images/emoji/blossom.png


    BIN
    simditor/static/simditor/images/emoji/blowfish.png


    BIN
    simditor/static/simditor/images/emoji/blue_book.png


    BIN
    simditor/static/simditor/images/emoji/blue_car.png


    BIN
    simditor/static/simditor/images/emoji/blue_heart.png


    BIN
    simditor/static/simditor/images/emoji/blush.png


    BIN
    simditor/static/simditor/images/emoji/boar.png


    BIN
    simditor/static/simditor/images/emoji/boat.png


    BIN
    simditor/static/simditor/images/emoji/bomb.png


    BIN
    simditor/static/simditor/images/emoji/book.png


    BIN
    simditor/static/simditor/images/emoji/bookmark.png


    BIN
    simditor/static/simditor/images/emoji/bookmark_tabs.png


    BIN
    simditor/static/simditor/images/emoji/books.png


    BIN
    simditor/static/simditor/images/emoji/boom.png


    BIN
    simditor/static/simditor/images/emoji/boot.png


    BIN
    simditor/static/simditor/images/emoji/bouquet.png


    BIN
    simditor/static/simditor/images/emoji/bow.png


    BIN
    simditor/static/simditor/images/emoji/bowling.png


    BIN
    simditor/static/simditor/images/emoji/bowtie.png


    BIN
    simditor/static/simditor/images/emoji/boy.png


    BIN
    simditor/static/simditor/images/emoji/bread.png


    BIN
    simditor/static/simditor/images/emoji/bride_with_veil.png


    BIN
    simditor/static/simditor/images/emoji/bridge_at_night.png


    BIN
    simditor/static/simditor/images/emoji/briefcase.png


    BIN
    simditor/static/simditor/images/emoji/broken_heart.png


    BIN
    simditor/static/simditor/images/emoji/bug.png


    BIN
    simditor/static/simditor/images/emoji/bulb.png


    BIN
    simditor/static/simditor/images/emoji/bullettrain_front.png


    BIN
    simditor/static/simditor/images/emoji/bullettrain_side.png


    BIN
    simditor/static/simditor/images/emoji/bus.png


    BIN
    simditor/static/simditor/images/emoji/busstop.png


    BIN
    simditor/static/simditor/images/emoji/bust_in_silhouette.png


    BIN
    simditor/static/simditor/images/emoji/busts_in_silhouette.png


    BIN
    simditor/static/simditor/images/emoji/cactus.png


    BIN
    simditor/static/simditor/images/emoji/cake.png


    BIN
    simditor/static/simditor/images/emoji/calendar.png


    BIN
    simditor/static/simditor/images/emoji/calling.png


    BIN
    simditor/static/simditor/images/emoji/camel.png


    BIN
    simditor/static/simditor/images/emoji/camera.png


    BIN
    simditor/static/simditor/images/emoji/cancer.png


    BIN
    simditor/static/simditor/images/emoji/candy.png


    BIN
    simditor/static/simditor/images/emoji/capital_abcd.png


    BIN
    simditor/static/simditor/images/emoji/capricorn.png


    BIN
    simditor/static/simditor/images/emoji/car.png


    BIN
    simditor/static/simditor/images/emoji/card_index.png


    BIN
    simditor/static/simditor/images/emoji/carousel_horse.png


    BIN
    simditor/static/simditor/images/emoji/cat.png


    BIN
    simditor/static/simditor/images/emoji/cat2.png


    BIN
    simditor/static/simditor/images/emoji/cd.png


    BIN
    simditor/static/simditor/images/emoji/chart.png


    BIN
    simditor/static/simditor/images/emoji/chart_with_downwards_trend.png


    BIN
    simditor/static/simditor/images/emoji/chart_with_upwards_trend.png


    BIN
    simditor/static/simditor/images/emoji/checkered_flag.png


    BIN
    simditor/static/simditor/images/emoji/cherries.png


    BIN
    simditor/static/simditor/images/emoji/cherry_blossom.png


    BIN
    simditor/static/simditor/images/emoji/chestnut.png


    BIN
    simditor/static/simditor/images/emoji/chicken.png


    BIN
    simditor/static/simditor/images/emoji/children_crossing.png


    BIN
    simditor/static/simditor/images/emoji/chocolate_bar.png


    BIN
    simditor/static/simditor/images/emoji/christmas_tree.png


    BIN
    simditor/static/simditor/images/emoji/church.png


    BIN
    simditor/static/simditor/images/emoji/cinema.png


    BIN
    simditor/static/simditor/images/emoji/circus_tent.png


    BIN
    simditor/static/simditor/images/emoji/city_sunrise.png


    BIN
    simditor/static/simditor/images/emoji/city_sunset.png


    BIN
    simditor/static/simditor/images/emoji/cl.png


    BIN
    simditor/static/simditor/images/emoji/clap.png


    BIN
    simditor/static/simditor/images/emoji/clapper.png


    BIN
    simditor/static/simditor/images/emoji/clipboard.png


    BIN
    simditor/static/simditor/images/emoji/clock1.png


    BIN
    simditor/static/simditor/images/emoji/clock10.png


    BIN
    simditor/static/simditor/images/emoji/clock1030.png


    BIN
    simditor/static/simditor/images/emoji/clock11.png


    BIN
    simditor/static/simditor/images/emoji/clock1130.png


    BIN
    simditor/static/simditor/images/emoji/clock12.png


    BIN
    simditor/static/simditor/images/emoji/clock1230.png


    BIN
    simditor/static/simditor/images/emoji/clock130.png


    BIN
    simditor/static/simditor/images/emoji/clock2.png


    BIN
    simditor/static/simditor/images/emoji/clock230.png


    BIN
    simditor/static/simditor/images/emoji/clock3.png


    BIN
    simditor/static/simditor/images/emoji/clock330.png


    BIN
    simditor/static/simditor/images/emoji/clock4.png


    BIN
    simditor/static/simditor/images/emoji/clock430.png


    BIN
    simditor/static/simditor/images/emoji/clock5.png


    BIN
    simditor/static/simditor/images/emoji/clock530.png


    BIN
    simditor/static/simditor/images/emoji/clock6.png


    BIN
    simditor/static/simditor/images/emoji/clock630.png


    BIN
    simditor/static/simditor/images/emoji/clock7.png


    BIN
    simditor/static/simditor/images/emoji/clock730.png


    BIN
    simditor/static/simditor/images/emoji/clock8.png


    BIN
    simditor/static/simditor/images/emoji/clock830.png


    BIN
    simditor/static/simditor/images/emoji/clock9.png


    BIN
    simditor/static/simditor/images/emoji/clock930.png


    BIN
    simditor/static/simditor/images/emoji/closed_book.png


    BIN
    simditor/static/simditor/images/emoji/closed_lock_with_key.png


    BIN
    simditor/static/simditor/images/emoji/closed_umbrella.png


    BIN
    simditor/static/simditor/images/emoji/cloud.png


    BIN
    simditor/static/simditor/images/emoji/clubs.png


    BIN
    simditor/static/simditor/images/emoji/cn.png


    BIN
    simditor/static/simditor/images/emoji/cocktail.png


    BIN
    simditor/static/simditor/images/emoji/coffee.png


    BIN
    simditor/static/simditor/images/emoji/cold_sweat.png


    BIN
    simditor/static/simditor/images/emoji/collision.png


    BIN
    simditor/static/simditor/images/emoji/computer.png


    BIN
    simditor/static/simditor/images/emoji/confetti_ball.png


    BIN
    simditor/static/simditor/images/emoji/confounded.png


    BIN
    simditor/static/simditor/images/emoji/confused.png


    BIN
    simditor/static/simditor/images/emoji/congratulations.png


    BIN
    simditor/static/simditor/images/emoji/construction.png


    BIN
    simditor/static/simditor/images/emoji/construction_worker.png


    BIN
    simditor/static/simditor/images/emoji/convenience_store.png


    BIN
    simditor/static/simditor/images/emoji/cookie.png


    BIN
    simditor/static/simditor/images/emoji/cool.png


    BIN
    simditor/static/simditor/images/emoji/cop.png


    BIN
    simditor/static/simditor/images/emoji/copyright.png


    BIN
    simditor/static/simditor/images/emoji/corn.png


    BIN
    simditor/static/simditor/images/emoji/couple.png


    BIN
    simditor/static/simditor/images/emoji/couple_with_heart.png


    BIN
    simditor/static/simditor/images/emoji/couplekiss.png


    BIN
    simditor/static/simditor/images/emoji/cow.png


    BIN
    simditor/static/simditor/images/emoji/cow2.png


    BIN
    simditor/static/simditor/images/emoji/credit_card.png


    BIN
    simditor/static/simditor/images/emoji/crocodile.png


    BIN
    simditor/static/simditor/images/emoji/crossed_flags.png


    BIN
    simditor/static/simditor/images/emoji/crown.png


    BIN
    simditor/static/simditor/images/emoji/cry.png


    BIN
    simditor/static/simditor/images/emoji/crying_cat_face.png


    BIN
    simditor/static/simditor/images/emoji/crystal_ball.png


    BIN
    simditor/static/simditor/images/emoji/cupid.png


    BIN
    simditor/static/simditor/images/emoji/curly_loop.png


    BIN
    simditor/static/simditor/images/emoji/currency_exchange.png


    BIN
    simditor/static/simditor/images/emoji/curry.png


    BIN
    simditor/static/simditor/images/emoji/custard.png


    BIN
    simditor/static/simditor/images/emoji/customs.png


    BIN
    simditor/static/simditor/images/emoji/cyclone.png


    BIN
    simditor/static/simditor/images/emoji/dancer.png


    BIN
    simditor/static/simditor/images/emoji/dancers.png


    BIN
    simditor/static/simditor/images/emoji/dango.png


    BIN
    simditor/static/simditor/images/emoji/dart.png


    BIN
    simditor/static/simditor/images/emoji/dash.png


    BIN
    simditor/static/simditor/images/emoji/date.png


    BIN
    simditor/static/simditor/images/emoji/de.png


    BIN
    simditor/static/simditor/images/emoji/deciduous_tree.png


    BIN
    simditor/static/simditor/images/emoji/department_store.png


    BIN
    simditor/static/simditor/images/emoji/diamond_shape_with_a_dot_inside.png


    BIN
    simditor/static/simditor/images/emoji/diamonds.png


    BIN
    simditor/static/simditor/images/emoji/disappointed.png


    BIN
    simditor/static/simditor/images/emoji/dizzy.png


    BIN
    simditor/static/simditor/images/emoji/dizzy_face.png


    BIN
    simditor/static/simditor/images/emoji/do_not_litter.png


    BIN
    simditor/static/simditor/images/emoji/dog.png


    BIN
    simditor/static/simditor/images/emoji/dog2.png


    BIN
    simditor/static/simditor/images/emoji/dollar.png


    BIN
    simditor/static/simditor/images/emoji/dolls.png


    BIN
    simditor/static/simditor/images/emoji/dolphin.png


    BIN
    simditor/static/simditor/images/emoji/door.png


    BIN
    simditor/static/simditor/images/emoji/doughnut.png


    BIN
    simditor/static/simditor/images/emoji/dragon.png


    BIN
    simditor/static/simditor/images/emoji/dragon_face.png


    BIN
    simditor/static/simditor/images/emoji/dress.png


    BIN
    simditor/static/simditor/images/emoji/dromedary_camel.png


    BIN
    simditor/static/simditor/images/emoji/droplet.png


    BIN
    simditor/static/simditor/images/emoji/dvd.png


    BIN
    simditor/static/simditor/images/emoji/e-mail.png


    BIN
    simditor/static/simditor/images/emoji/ear.png


    BIN
    simditor/static/simditor/images/emoji/ear_of_rice.png


    BIN
    simditor/static/simditor/images/emoji/earth_africa.png


    BIN
    simditor/static/simditor/images/emoji/earth_americas.png


    BIN
    simditor/static/simditor/images/emoji/earth_asia.png


    BIN
    simditor/static/simditor/images/emoji/egg.png


    BIN
    simditor/static/simditor/images/emoji/eggplant.png


    BIN
    simditor/static/simditor/images/emoji/eight.png


    BIN
    simditor/static/simditor/images/emoji/eight_pointed_black_star.png


    BIN
    simditor/static/simditor/images/emoji/eight_spoked_asterisk.png


    BIN
    simditor/static/simditor/images/emoji/eightball.png


    BIN
    simditor/static/simditor/images/emoji/electric_plug.png


    BIN
    simditor/static/simditor/images/emoji/elephant.png


    BIN
    simditor/static/simditor/images/emoji/email.png


    + 0 - 0
    simditor/static/simditor/images/emoji/emojify.css

    @@ -0,0 +1 @@

    kodo - Gogs: Go Git Service

    暫無描述

    JQ8Eskhrjp.txt 32B

      f29a60a010cd52465a97bc04c1248408