Bladeren bron

新增AI调用次数按月份哈希存储以及查询

zhuojiaxuan 1 week geleden
bovenliggende
commit
81e013930a
2 gewijzigde bestanden met toevoegingen van 105 en 1 verwijderingen
  1. 84 1
      Controller/AiController.py
  2. 21 0
      Object/RedisObject.py

+ 84 - 1
Controller/AiController.py

@@ -39,7 +39,7 @@ from Service.CommonService import CommonService
 from Service.DevicePushService import DevicePushService
 from Service.EquipmentInfoService import EquipmentInfoService
 from Object.NovaImageTagObject import NovaImageTagObject
-from datetime import datetime
+from datetime import datetime, timedelta
 from django.conf import settings
 AWS_ACCESS_KEY_ID = settings.AWS_ACCESS_KEY_ID
 AWS_SECRET_ACCESS_KEY = settings.AWS_SECRET_ACCESS_KEY
@@ -78,6 +78,8 @@ class AiView(View):
             return response.json(444, 'error path')
         elif operation == 'identification':  # ai识别
             return self.do_ai_identification(request.POST, response)
+        elif operation == 'aiPushStats':  # ai调用统计
+            return self.ai_push_stats(request_dict, response)
         else:
             token = request_dict.get('token', None)
             # 设备主键uid
@@ -133,6 +135,11 @@ class AiView(View):
             ai_data = redis_obj.get_data(ai_key)
             if ai_data:
                 return response.json(0, {'msg': 'Push again in one minute'})
+            # === AI 调用计数===
+            n_time_int = int(n_time) if n_time else int(time.time())
+            date_str = time.strftime("%Y%m%d", time.localtime(n_time_int))
+            self.ai_push_count(uid, date_str)
+            # =========================================
             # 查询推送数据
             uid_push_qs = UidPushModel.objects.filter(uid_set__uid=uid). \
                 values('token_val', 'app_type', 'appBundleId', 'm_code', 'push_type', 'userID_id',
@@ -794,3 +801,79 @@ class AiView(View):
             f'执行时间: {execution_time:.4f}秒'
         )
         return final_results
+
+    @staticmethod
+    def ai_push_count(uid, date_str):
+        """ 记录 AI 调用次数(按月累计) """
+        redis_obj = RedisObject(db=7)
+        month_str = date_str[:6]  # "202511"
+        key = f"ai:push:monthly:{month_str}"
+        ttl = 3600 * 24 * 365
+        try:
+            redis_obj.hash_field_increment(key, uid, 1, ttl)
+        except Exception as e:
+            TIME_LOGGER.error(f"AI调用计数失败 uid={uid} error={repr(e)}")
+
+    def ai_push_stats(self, request_dict, response):
+        uid = request_dict.get('uid', None)
+        start = request_dict.get('start_time')
+        end = request_dict.get('end_time')
+
+        if not all([start, end]):
+            return response.json(444)
+
+        try:
+            start_dt = datetime.strptime(start, "%Y-%m")
+            end_dt = datetime.strptime(end, "%Y-%m")
+        except ValueError:
+            return response.json(444, '月份格式错误,必须为 YYYY-MM')
+
+        if start_dt > end_dt:
+            return response.json(444, '开始月份不能晚于结束月份')
+
+        redis_obj = RedisObject(db=7)
+        total = 0
+        monthly = []
+
+        # 当前月份从开始月份的1号开始
+        cur = start_dt
+        while cur <= end_dt:
+            month_str = cur.strftime("%Y%m")
+            key = f"ai:push:monthly:{month_str}"
+            month_data = {
+                "month": cur.strftime("%Y-%m"),
+                "total_count": 0,  # 当月总次数
+                "users": []  # 当月用户明细(uid和次数)
+            }
+
+            if uid:
+                #只返回该设备的数据
+                count = redis_obj.CONN.hget(key, uid)
+                count = int(count) if count else 0
+                month_data["total_count"] = count
+                month_data["users"].append({"uid": uid, "count": count})
+            else:
+                #返回所有设备的明细和总次数
+                data = redis_obj.CONN.hgetall(key)
+                user_list = []
+                total_month = 0
+                for user_uid, cnt in data.items():
+                    uid_str = user_uid.decode('utf-8')
+                    count_int = int(cnt.decode('utf-8'))
+                    user_list.append({"uid": uid_str, "count": count_int})
+                    total_month += count_int
+                month_data["total_count"] = total_month
+                month_data["users"] = user_list
+
+            total += month_data["total_count"]
+            monthly.append(month_data)
+
+            cur += timedelta(days=32)
+            cur = cur.replace(day=1)
+
+        result = {
+            "uid": uid,
+            "total": total,  # 所有月份的总和
+            "monthly": monthly  # 每个月的明细
+        }
+        return response.json(0, result)

+ 21 - 0
Object/RedisObject.py

@@ -130,4 +130,25 @@ class RedisObject:
             return result
         except Exception as e:
             print(repr(e))
+            return False
+
+    def hash_field_increment(self, key, field, val=1, ttl=0):
+        """
+        哈希表中字段增量
+        :param key: redis的key
+        :param field: 哈希表字段
+        :param val: 增量
+        :param ttl: 键的过期时间(秒)
+        :return: 成功返回True 异常返回 False
+        """
+        try:
+            # 增加哈希表中指定字段的值
+            self.CONN.hincrby(key, field, val)
+            # 如果 ttl 大于 0,则设置过期时间(单位:秒)
+            if ttl > 0:
+                self.CONN.expire(key, ttl)
+            return True
+        except Exception as e:
+            # 发生异常时打印错误信息,便于调试
+            print(f"增值或设置过期时间时发生错误: {repr(e)}")
             return False