瀏覽代碼

APP开屏广告 后台接口+APP业务接口

linhaohong 1 年之前
父節點
當前提交
9d38a758c0
共有 3 個文件被更改,包括 248 次插入76 次删除
  1. 1 1
      AdminController/LogManagementController.py
  2. 241 70
      Controller/AppCampaignController.py
  3. 6 5
      Model/models.py

+ 1 - 1
AdminController/LogManagementController.py

@@ -336,7 +336,7 @@ class LogManagementView(View):
             )
             for app_log in app_log_list:
                 filename = app_log['filename']
-                if not filename.endswith('.txt') and not filename.endswith('.db'):
+                if not filename.endswith('.txt'):
                     filename += ".txt"
                 obj = 'app_log/' + app_log['user_id'] + '/{}'.format(filename)
                 appLog_url = aws_s3_client.generate_presigned_url(

+ 241 - 70
Controller/AppCampaignController.py

@@ -2,10 +2,10 @@ import time
 import pytz
 import json
 from datetime import datetime
+from datetime import time as Time
 
-from Model.models import AppAdvertiseCampaign, DeviceTypeModel, CountryModel
-from Ansjer.config import OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, \
-    AWS_SES_ACCESS_REGION, UNUSED_SERIAL_REDIS_LIST
+from Model.models import AppAdvertiseCampaign, DeviceTypeModel, CountryModel, Device_User, OpenScreenCampaign
+from Ansjer.config import AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, SERVER_TYPE
 
 from django.core.paginator import Paginator
 from django.views import View
@@ -14,6 +14,8 @@ from django.db.models import Q
 
 from Object.AWS.AmazonS3Util import AmazonS3Util
 from Object.ResponseObject import ResponseObject
+from Object.TokenObject import TokenObject
+
 
 class AppCampaignView(View):
     def get(self, request, *args, **kwargs):
@@ -33,20 +35,22 @@ class AppCampaignView(View):
         response = ResponseObject(language, 'pc')
         if operation == 'getCampaignList':  # 获取广告活动列表
             return self.get_campaign_list(request_dict, response)
-        elif operation == 'addCampaign': # 添加广告活动
+        elif operation == 'addCampaign':  # 添加广告活动
             return self.add_campaign(request, request_dict, response)
-        elif operation == 'updateCampaign': # 更新广告活动
+        elif operation == 'updateCampaign':  # 更新广告活动
             return self.update_campaign(request, request_dict, response)
-        elif operation == 'deleteCampaign': # 删除广告活动
+        elif operation == 'deleteCampaign':  # 删除广告活动
             return self.delete_campaign(request_dict, response)
-        elif operation == 'switchCampaign': # 广告活动开关
+        elif operation == 'switchCampaign':  # 广告活动开关
             return self.switch_campaign(request_dict, response)
-        elif operation == 'recordUserBehavior':
-            return self.record_user_behavior(request_dict, response)
         elif operation == 'appGetCampaigns':
             return self.app_get_campaigns(request_dict, response)
+        elif operation == 'recordUserBehavior':
+            return self.record_user_behavior(request_dict, response)
+        elif operation == 'getUserBehaviorLog':
+            return self.get_user_behavior_log(request_dict, response)
         else:
-            return response.json(404)
+            return response.json(414)
 
     def get_campaign_list(self, request_dict, response):
         """
@@ -63,9 +67,12 @@ class AppCampaignView(View):
         unknown_country = 0
 
         # 连接并获取国家和设备类型
-        country_prefetch = Prefetch('country', queryset=CountryModel.objects.only('country_name'), to_attr='country_list')
-        device_type_prefetch = Prefetch('device_type', queryset=DeviceTypeModel.objects.only('name'), to_attr='device_type_list')
-        app_advertise_campaign_qs = AppAdvertiseCampaign.objects.prefetch_related(country_prefetch, device_type_prefetch)
+        country_prefetch = Prefetch('country', queryset=CountryModel.objects.only('country_name'),
+                                    to_attr='country_list')
+        device_type_prefetch = Prefetch('device_type', queryset=DeviceTypeModel.objects.only('name'),
+                                        to_attr='device_type_list')
+        app_advertise_campaign_qs = AppAdvertiseCampaign.objects.prefetch_related(country_prefetch,
+                                                                                  device_type_prefetch)
 
         # 过滤
         if campaign_name:
@@ -76,12 +83,19 @@ class AppCampaignView(View):
             campaign_country_list = campaign_country.split(',')
             if "未知地区" in campaign_country_list:
                 unknown_country = 1
-            app_advertise_campaign_qs = app_advertise_campaign_qs.filter(Q(country__country_name__in=campaign_country_list) | Q(unknown_country=unknown_country)).distinct()
+            app_advertise_campaign_qs = app_advertise_campaign_qs.filter(
+                Q(country__country_name__in=campaign_country_list) | Q(unknown_country=unknown_country)).distinct()
+        app_advertise_campaign_qs = app_advertise_campaign_qs.filter(~Q(status=2))
         # 分页
         paginator = Paginator(app_advertise_campaign_qs.order_by('id'), pageSize)
         campaigns = paginator.page(pageNo)
 
-        # Construct response data with country names and device types
+        if SERVER_TYPE == 'Ansjer.cn_config.formal_settings' or SERVER_TYPE == 'Ansjer.cn_config.test_settings':
+            s3_url = "https://ansjerfilemanager.s3.cn-northwest-1.amazonaws.com.cn/app/campaign/"
+        else:
+            s3_url = "https://ansjerfilemanager.s3.amazonaws.com/app/campaign/"
+
+        # 添加设备名和地区返回
         campaign_list = []
         for campaign in campaigns.object_list:
             if campaign.unknown_country == 0:
@@ -95,7 +109,7 @@ class AppCampaignView(View):
                 countries = ",".join(country_names)
             campaign_data = {
                 'id': campaign.id,
-                'image_url': 'https://ansjerfilemanager.s3.amazonaws.com/app/campaign/' + campaign.image_url,
+                'image_url': s3_url + campaign.image_url,
                 'campaign_name': campaign.campaign_name,
                 'campaign_url': campaign.campaign_url,
                 'campaign_type': campaign.campaign_type,
@@ -144,7 +158,12 @@ class AppCampaignView(View):
         if "未知地区" in country_name_list:
             unknown_country = 1
             country_name_list.remove("未知地区")
-
+        if SERVER_TYPE == 'Ansjer.cn_config.formal_settings' or SERVER_TYPE == 'Ansjer.cn_config.test_settings':
+            regin = 0
+            AWS_SES_ACCESS_REGION = "cn-northwest-1"
+        else:
+            regin = 1
+            AWS_SES_ACCESS_REGION = 'us-east-1'
         fileName = file.name
         try:
             create_time = int(time.time())
@@ -152,7 +171,7 @@ class AppCampaignView(View):
             # 保存图片到存储桶
             bucket_name = 'ansjerfilemanager'
             file_key = f'app/campaign/OpenScreenAdvertise/{update_time}_{fileName}'
-            s3 = AmazonS3Util(AWS_ACCESS_KEY_ID[1], AWS_SECRET_ACCESS_KEY[1], AWS_SES_ACCESS_REGION)
+            s3 = AmazonS3Util(AWS_ACCESS_KEY_ID[0], AWS_SECRET_ACCESS_KEY[0], "cn-northwest-1")
             # 地址:https://ansjerfilemanager.s3.amazonaws.com/app/campaign/OpenScreenAdvertise/XXX.jpg
             s3.upload_file_obj(
                 bucket_name,
@@ -186,25 +205,32 @@ class AppCampaignView(View):
                 new_campaign.country.add(country_instance)
 
         except Exception as e:
-            return response.json(174)
+            return response.json(178)
 
         return response.json(0)
 
     def update_campaign(self, request, request_dict, response):
         campaign_id = request_dict.get('id', None)
-        file = request.FILES.get('posterFile', None)
         campaign_name = request_dict.get('campaign_name', None)
         campaign_url = request_dict.get('campaign_url', None)
         campaign_type = request_dict.get('campaign_type', None)
-        device_type_names = json.loads(request_dict.get('device_type_list', None))  # 设备类型名称列表
-        country_name_list = json.loads(request_dict.get('country_name_list', None))  # 地区列表
+        device_type_names = json.loads(request_dict.get('device_type_list', '[]'))  # 设备类型名称列表
+        country_name_list = json.loads(request_dict.get('country_name_list', '[]'))  # 地区列表
         campaign_start_time = request_dict.get('campaign_start_time', None)
         campaign_end_time = request_dict.get('campaign_end_time', None)
         campaign_show_stime = request_dict.get('campaign_show_stime', None)
         campaign_show_etime = request_dict.get('campaign_show_etime', None)
+        file = request.FILES.get('posterFile', None)
         if not campaign_id:
             return response.json(444)
 
+        if SERVER_TYPE == 'Ansjer.cn_config.formal_settings' or SERVER_TYPE == 'Ansjer.cn_config.test_settings':
+            regin = 0
+            AWS_SES_ACCESS_REGION = "cn-northwest-1"
+        else:
+            regin = 1
+            AWS_SES_ACCESS_REGION = 'us-east-1'
+
         try:
             update_time = int(time.time())
             campaign = AppAdvertiseCampaign.objects.get(id=campaign_id)
@@ -216,11 +242,10 @@ class AppCampaignView(View):
                     campaign.unknown_country = 0
             if file is not None:
                 # 删除存储桶原来的图片
-                s3 = AmazonS3Util(AWS_ACCESS_KEY_ID[1], AWS_SECRET_ACCESS_KEY[1], AWS_SES_ACCESS_REGION)
+                s3 = AmazonS3Util(AWS_ACCESS_KEY_ID[regin], AWS_SECRET_ACCESS_KEY[regin], AWS_SES_ACCESS_REGION)
                 bucket_name = 'ansjerfilemanager'
                 if campaign.image_url:
-                    old_file_key = campaign.image_url.split('/')[-1]
-                    s3.delete_obj(bucket_name, old_file_key)
+                    s3.delete_obj(bucket_name, f"app/campaign/{campaign.image_url}")
                 # 添加新的图片
                 file_key = f'app/campaign/OpenScreenAdvertise/{update_time}_{file.name}'
                 s3.upload_file_obj(
@@ -270,82 +295,228 @@ class AppCampaignView(View):
         if not campaign_id:
             return response.json(444)
         try:
-            campaign = AppAdvertiseCampaign.objects.get(pk=campaign_id)
-            # 更新字段
-            campaign.status = status
-            campaign.update_time = int(time.time())
-            # 保存更改
-            campaign.save()
+            AppAdvertiseCampaign.objects.filter(pk=campaign_id).update(status=status, update_time=int(time.time()))
             return response.json(0)
         except Exception as e:
             return response.json(444)
 
     def delete_campaign(self, request_dict, response):
         campaign_id = request_dict.get('id')
+        if SERVER_TYPE == 'Ansjer.cn_config.formal_settings' or SERVER_TYPE == 'Ansjer.cn_config.test_settings':
+            regin = 0
+            AWS_SES_ACCESS_REGION = "cn-northwest-1"
+        else:
+            regin = 1
+            AWS_SES_ACCESS_REGION = 'us-east-1'
         if not campaign_id:
             return response.json(444)
         try:
-            campaign = AppAdvertiseCampaign.objects.get(id=campaign_id)
+            campaign = AppAdvertiseCampaign.objects.get(pk=campaign_id)
+            s3 = AmazonS3Util(AWS_ACCESS_KEY_ID[regin], AWS_SECRET_ACCESS_KEY[regin], AWS_SES_ACCESS_REGION)
+            bucket_name = 'ansjerfilemanager'
+            if campaign.image_url:
+                s3.delete_obj(bucket_name, f"app/campaign/{campaign.image_url}")
+            # 清除多对多关系
             campaign.device_type.clear()
             campaign.country.clear()
-            campaign.delete()
+            # 保留在广告表中
+            campaign.status = 2
+            campaign.update_time = int(time.time())
+            campaign.save()
             return response.json(0)
+
         except Exception as e:
-            return response.json(444)
+            return response.json(176)
 
-    def app_get_campaigns(self, request_dict, response):
+    def get_timezone_offset(self, tz):
+        """
+        UTC-8格式转化
+        """
+        sign = tz[3]  # "+" 或 "-"
+        hours = int(tz[4:])  # 时差小时数
+        timezone_name = f"Etc/GMT{sign}{hours}" if sign == "-" else f"Etc/GMT+{hours}"
+        return pytz.timezone(timezone_name)
+
+    def app_get_campaigns(cls, request_dict, response):
         """
         APP获取广告活动列表
         @param request_dict: 请求参数
         @param response: 响应对象
         @return: 响应对象
         """
-        tz = request_dict.get('时区','tz')
-
-        country_prefetch = Prefetch('country', queryset=CountryModel.objects.only('country_name'), to_attr='country_list')
-        device_type_prefetch = Prefetch('device_type', queryset=DeviceTypeModel.objects.only('name'), to_attr='device_type_list')
-        app_advertise_campaign_qs = AppAdvertiseCampaign.objects.prefetch_related(country_prefetch, device_type_prefetch)
-        app_advertise_campaign_qs = (app_advertise_campaign_qs.objects.filter(status=1,)
-                                     .values('image_url', 'campaign_name', 'campaign_type',
-                                             'campaign_start_time', 'campaign_end_time',
-                                             'campaign_show_stime', 'campaign_show_etime',
-                                             ))
-        #返回 广告名称、广告类型、开始时间、结束时间、广告图片、活动链接
-        campaigns_list = []
-
-        # 调整时区返回时间
-        for campaign in app_advertise_campaign_qs:
-            # 将时间戳转换为UTC的datetime对象
-            start_utc_time = datetime.utcfromtimestamp(int(campaign['campaign_start_time'])).replace(tzinfo=pytz.utc)
-            end_utc_time = datetime.utcfromtimestamp(int(campaign['campaign_end_time'])).replace(tzinfo=pytz.utc)
-            campaigns_list.append(campaign)
-
-        return response.json(0,{
-            'campaigns': campaigns_list
-        })
-
-    def record_user_behavior(self, request_dict, response):
+        tz = request_dict.get('tz', 'UTC+0')
+        token = request_dict.get('token', None)
+        if not token:
+            return response.json(444)
+        token = TokenObject(token)
+        if token.code != 0:
+            return response.json(token.code)
+        user_id = token.userID
+
+        if SERVER_TYPE == 'Ansjer.cn_config.formal_settings' or SERVER_TYPE == 'Ansjer.cn_config.test_settings':
+            s3_url = "https://ansjerfilemanager.s3.cn-northwest-1.amazonaws.com.cn/app/campaign/"
+        else:
+            s3_url = "https://ansjerfilemanager.s3.amazonaws.com/app/campaign/"
+
+        # 当日时间戳区间获取
+        timezone = cls.get_timezone_offset(tz)
+        current_date = datetime.now().date()
+        start_of_day = datetime.combine(current_date, Time.min)
+        end_of_day = datetime.combine(current_date, Time.max)
+        start_timestamp = int(start_of_day.timestamp())
+        end_timestamp = int(end_of_day.timestamp())
+
+        open_screen_campaign_qs = OpenScreenCampaign.objects.filter(
+            user_id=user_id,
+            create_time__gt=start_timestamp,
+            create_time__lt=end_timestamp
+        )
+        if not open_screen_campaign_qs.exists():
+            OpenScreenCampaign.objects.create(user_id=user_id,
+                                              create_time=int(time.time()))
+        try:
+            country_prefetch = Prefetch('country', queryset=CountryModel.objects.only('id'), to_attr='country_list')
+            device_type_prefetch = Prefetch('device_type', queryset=DeviceTypeModel.objects.only('type'),
+                                            to_attr='device_type_list')
+            app_advertise_campaign_qs = AppAdvertiseCampaign.objects.prefetch_related(country_prefetch,
+                                                                                      device_type_prefetch)
+
+            device_info_qs = Device_User.objects.filter(userID=user_id).values("region_country").first()
+            country_id = device_info_qs.get('region_country')
+            if country_id != 0:
+                app_advertise_campaign_qs = app_advertise_campaign_qs.filter(country__id=country_id, status=1)
+            else:
+                app_advertise_campaign_qs = app_advertise_campaign_qs.filter(status=1, unknown_country=1)
+
+            # 返回 广告名称、广告类型、开始时间、结束时间、广告图片、活动链接
+            campaigns_list = []
+
+            for campaign in app_advertise_campaign_qs:
+                # 时区处理
+                campaigns_start_date = (datetime.utcfromtimestamp(campaign.campaign_start_date)
+                                        .replace(tzinfo=pytz.utc).astimezone(timezone).strftime('%Y-%m-%d'))
+                campaign_end_date = (datetime.utcfromtimestamp(campaign.campaign_end_date)
+                                     .replace(tzinfo=pytz.utc).astimezone(timezone).strftime('%Y-%m-%d'))
+                campaign_start_firstday = (
+                    datetime.utcfromtimestamp(campaign.campaign_start_date + campaign.campaign_show_stime)
+                    .replace(tzinfo=pytz.utc).astimezone(timezone).strftime('%Y-%m-%d %H:%M'))
+                campaign_end_firstday = (
+                    datetime.utcfromtimestamp(campaign.campaign_start_date + campaign.campaign_show_etime)
+                    .replace(tzinfo=pytz.utc).astimezone(timezone).strftime('%Y-%m-%d %H:%M'))
+                campaigns_list.append({
+                    'campaign_id': campaign.id,
+                    'image_url': s3_url + campaign.image_url,
+                    'campaign_url': campaign.campaign_url,
+                    'campaign_name': campaign.campaign_name,
+                    'campaign_type': campaign.campaign_type,
+                    'campaign_date': f"{campaigns_start_date},{campaign_end_date}",
+                    'campaign_start_oneday': campaign_start_firstday,
+                    'campaign_end_oneday': campaign_end_firstday,
+                    'device_types': [device.type for device in campaign.device_type_list],
+                })
+            return response.json(0, {
+                'campaigns': campaigns_list
+            })
+        except Exception as e:
+            return response.json(173)
+
+    def record_user_behavior(cls, request_dict, response):
         """
         记录用户行为
         @param request_dict: 请求参数
         @param response: 响应对象
         @return: 响应对象
         """
-        pass
-
-
-
-
-
-
-
-
-
+        status = request_dict.get('status', None)  # 1.未跳过 2.已跳过 3.点击广告
+        campaign_id = request_dict.get('campaign_id', None)
+        token = request_dict.get('token', None)
+        if not token:
+            return response.json(444)
+        token = TokenObject(token)
+        if token.code != 0:
+            return response.json(token.code)
+        user_id = token.userID
 
+        if not all([status, campaign_id]):
+            return response.json(444)
 
+        # 当日时间(各个时区都不同)戳区间获取
+        current_date = datetime.now().date()
+        start_of_day = datetime.combine(current_date, Time.min)
+        end_of_day = datetime.combine(current_date, Time.max)
+        start_timestamp = int(start_of_day.timestamp())
+        end_timestamp = int(end_of_day.timestamp())
 
+        try:
+            # 筛选符合条件的记录
+            open_screen_campaigns = OpenScreenCampaign.objects.filter(
+                user_id=user_id,
+                create_time__gt=start_timestamp,
+                create_time__lt=end_timestamp,
+                status=0,
+            )
 
+            # 检查是否存在记录
+            if not open_screen_campaigns.exists():
+                # 如果不存在,则创建新记录
+                OpenScreenCampaign.objects.create(
+                    user_id=user_id,
+                    status=status,
+                    campaign_id_id=campaign_id,
+                    create_time=int(time.time()),
+                    update_time=int(time.time())
+                )
 
+            else:
+                # 如果存在,则更新最新的记录
+                latest_campaign = open_screen_campaigns.latest("create_time")
+                latest_campaign.status = status
+                latest_campaign.campaign_id_id = campaign_id
+                latest_campaign.update_time = int(time.time())
+                latest_campaign.save()
 
+        except Exception as e:
+            return response.json(177, {'error': '更新错误'})
 
+        return response.json(0)
 
+    def get_user_behavior_log(self, request_dict, response):
+        status = request_dict.get('status', None)
+        user_id = request_dict.get('user_id', None)
+        behavior_stime = request_dict.get('start_time', None)
+        behavior_etime = request_dict.get('end_time', None)
+        page = request_dict.get('page', 1)  # 默认为第一页
+        page_size = request_dict.get('page_size', 10)  # 默认每页显示10条记录
+        behavior_log_list = []
+
+        open_screen_campaigns = OpenScreenCampaign.objects.all()
+        if user_id is not None:
+            open_screen_campaigns = open_screen_campaigns.filter(user_id=user_id)
+        if status is not None:
+            open_screen_campaigns = open_screen_campaigns.filter(status=status)
+        # 时间过滤
+        if behavior_stime is not None and behavior_etime is not None:
+            open_screen_campaigns = open_screen_campaigns.filter(update_time__range=[behavior_stime, behavior_etime])
+        elif behavior_stime is not None:
+            open_screen_campaigns = open_screen_campaigns.filter(update_time__gte=behavior_stime)
+        elif behavior_etime is not None:
+            open_screen_campaigns = open_screen_campaigns.filter(update_time__lte=behavior_etime)
+
+        if not open_screen_campaigns.exists():
+            return response.json(0, {"behavior_log_list": [], "total": 0})
+        # 分页
+        open_screen_campaigns = open_screen_campaigns.order_by('id')
+        paginator = Paginator(open_screen_campaigns, page_size)
+        open_screen_campaigns_page = paginator.page(page)
+
+        for campaign in open_screen_campaigns_page:
+            campaign_name = campaign.campaign_id.campaign_name if campaign.campaign_id else '广告不存在'
+            behavior_log_list.append({
+                "campaign_name": campaign_name,
+                "user_id": campaign.user_id,
+                "status": campaign.status,
+                "behavior_time": campaign.update_time
+            })
+
+        return response.json(0, {"behavior_log_list": behavior_log_list,
+                                 "total": paginator.count})

+ 6 - 5
Model/models.py

@@ -4245,15 +4245,16 @@ class AppAdvertiseCampaign(models.Model):
         db_table = 'app_advertise_campaign'
         verbose_name = 'App广告活动表'
 
-
 class OpenScreenCampaign(models.Model):
     id = models.AutoField(primary_key=True, verbose_name='主键')
-    campaign_id = models.ForeignKey(AppAdvertiseCampaign, on_delete=models.CASCADE, verbose_name='广告活动id')
-    username = models.CharField(default='', max_length=32, verbose_name='用户名')
+    campaign_id = models.ForeignKey(AppAdvertiseCampaign, blank=True, to_field='id', null=True,
+                                        on_delete=models.SET_NULL, db_constraint=False)
+    user_id = models.CharField(default='', max_length=32, verbose_name='userID')
     status = models.SmallIntegerField(default=0, verbose_name='广告状态')
     # 0未展示 1未跳过 2已跳过 3点击广告
-    campaign_show_time = models.IntegerField(default=0, verbose_name='广告展示时间')
+    update_time = models.IntegerField(default=0, verbose_name='更新时间')
+    create_time = models.IntegerField(default=0, verbose_name='创建时间')
 
     class Meta:
         db_table = 'open_screen_campaign'
-        verbose_name = '开屏广告表'
+        verbose_name = '开屏广告表'