增加目标追踪的模块

This commit is contained in:
2025-05-07 14:17:36 +08:00
parent da1f5a874e
commit 939e29c2d6
14 changed files with 256 additions and 503 deletions

View File

@ -6,7 +6,7 @@ import torch
from utils.yolov5.models.common import DetectMultiBackend from utils.yolov5.models.common import DetectMultiBackend
from utils.yolov5.utils.torch_utils import select_device from utils.yolov5.utils.torch_utils import select_device
from utils.yolov5.utils.dataloaders import LoadImages, LoadStreams from utils.yolov5.utils.dataloaders import LoadImages, LoadStreams
from utils.yolov5.utils.general import check_img_size, non_max_suppression, cv2, scale_coords, xyxy2xywh, Profile from utils.yolov5.utils.general import check_img_size, non_max_suppression, cv2, scale_coords, xyxy2xywh
from deep_sort.deep_sort import DeepSort from deep_sort.deep_sort import DeepSort
from deep_sort.utils.draw import draw_boxes from deep_sort.utils.draw import draw_boxes
@ -69,22 +69,17 @@ async def run_deepsort(
time.sleep(2) # 等待2s等待websocket进入 time.sleep(2) # 等待2s等待websocket进入
dt = (Profile(device=device), Profile(device=device), Profile(device=device))
for path, im, im0s, vid_cap, s in dataset: for path, im, im0s, vid_cap, s in dataset:
if room_manager.rooms.get(room): if room_manager.rooms.get(room):
with dt[0]: im0 = im0s[0]
im0 = im0s[0] im = torch.from_numpy(im).to(model.device)
im = torch.from_numpy(im).to(model.device) im = im.half() if model.fp16 else im.float() # uint8 to fp16/32
im = im.half() if model.fp16 else im.float() # uint8 to fp16/32 im /= 255 # 0 - 255 to 0.0 - 1.0
im /= 255 # 0 - 255 to 0.0 - 1.0 if len(im.shape) == 3:
if len(im.shape) == 3: im = im[None] # expand for batch dim
im = im[None] # expand for batch dim pred = model(im, augment=False, visualize=False)
with dt[1]: # NMS
pred = model(im, augment=False, visualize=False) pred = non_max_suppression(pred, 0.25, 0.45, None, False, max_det=1000)[0]
with dt[2]:
# NMS
pred = non_max_suppression(pred, 0.25, 0.45, None, False, max_det=1000)[0]
pred[:, :4] = scale_coords(im.shape[2:], pred[:, :4], im0.shape).round() pred[:, :4] = scale_coords(im.shape[2:], pred[:, :4], im0.shape).round()

View File

@ -8,7 +8,7 @@ from utils.yolov5.utils.torch_utils import select_device
from ultralytics.utils.plotting import Annotator, colors from ultralytics.utils.plotting import Annotator, colors
from utils.yolov5.models.common import DetectMultiBackend from utils.yolov5.models.common import DetectMultiBackend
from apps.business.deepsort import service as deepsort_service from apps.business.deepsort import service as deepsort_service
from utils.yolov5.utils.general import check_img_size, Profile, non_max_suppression, cv2, scale_boxes from utils.yolov5.utils.general import check_img_size, non_max_suppression, cv2, scale_boxes
import time import time
import torch import torch
@ -97,7 +97,7 @@ async def run_detect_img(
room = 'detect_' + str(detect_id) room = 'detect_' + str(detect_id)
await room_manager.send_to_room(room, f"AiCheck: 模型训练开始,请稍等。。。\n") await room_manager.send_to_room(room, f"AiCheck: 模型训练开始,请稍等。。。\n")
commend = ["python", '-u', yolo_path, "--weights", weights, "--source", source, "--name", name, "--project", commend = ["python", '-u', yolo_path, "--weights", weights, "--source", source, "--name", name, "--project",
project, "--save-txt", "--conf-thres", "0.4"] project, "--save-txt", "--conf-thres", "0.6"]
# 判断是否存在cuda版本 # 判断是否存在cuda版本
if is_gpu == 'True': if is_gpu == 'True':
commend.append("--device=0") commend.append("--device=0")
@ -176,25 +176,20 @@ async def run_detect_rtsp(weights_pt: str, rtsp_url: str, data: str, detect_id:
model.warmup(imgsz=(1 if pt or model.triton else bs, 3, *img_sz)) model.warmup(imgsz=(1 if pt or model.triton else bs, 3, *img_sz))
dt = (Profile(device=device), Profile(device=device), Profile(device=device)) time.sleep(3) # 等待3s等待websocket进入
time.sleep(3) # 等待2s等待websocket进入
for path, im, im0s, vid_cap, s in dataset: for path, im, im0s, vid_cap, s in dataset:
if room_manager.rooms.get(room): if room_manager.rooms.get(room):
with dt[0]: im = torch.from_numpy(im).to(model.device)
im = torch.from_numpy(im).to(model.device) im = im.half() if model.fp16 else im.float() # uint8 to fp16/32
im = im.half() if model.fp16 else im.float() # uint8 to fp16/32 im /= 255 # 0 - 255 to 0.0 - 1.0
im /= 255 # 0 - 255 to 0.0 - 1.0 if len(im.shape) == 3:
if len(im.shape) == 3: im = im[None] # expand for batch dim
im = im[None] # expand for batch dim
# Inference # Inference
with dt[1]: pred = model(im, augment=False, visualize=False)
pred = model(im, augment=False, visualize=False)
# NMS # NMS
with dt[2]: pred = non_max_suppression(pred, 0.25, 0.45, None, False, max_det=1000)
pred = non_max_suppression(pred, 0.25, 0.45, None, False, max_det=1000)
# Process predictions # Process predictions
for i, det in enumerate(pred): # per image for i, det in enumerate(pred): # per image

View File

@ -80,8 +80,6 @@ class LoginValidation:
await db.flush() await db.flush()
elif not user.is_active: elif not user.is_active:
self.result.msg = "此手机号已被冻结!" self.result.msg = "此手机号已被冻结!"
elif data.platform in ["0", "1"]:
self.result.msg = "此手机号无权限!"
else: else:
if not DEMO and count: if not DEMO and count:
await count.delete() await count.delete()

View File

@ -7,20 +7,16 @@
# @desc : 数据库 增删改查操作 # @desc : 数据库 增删改查操作
import json import json
from enum import Enum import os
from typing import Any from sqlalchemy import select, update
from redis.asyncio import Redis
from fastapi.encoders import jsonable_encoder
from motor.motor_asyncio import AsyncIOMotorDatabase
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import joinedload from sqlalchemy.orm import joinedload
from application.settings import SUBSCRIBE from application.settings import STATIC_ROOT, REDIS_DB_ENABLE
from core.mongo_manage import MongoManage from core.database import redis_getter
from utils.file.file_manage import FileManage
from . import models, schemas from . import models, schemas
from core.crud import DalBase from core.crud import DalBase
from core.exception import CustomException from fastapi import Request
from utils import status
class DictTypeDal(DalBase): class DictTypeDal(DalBase):
@ -67,323 +63,116 @@ class DictDetailsDal(DalBase):
self.schema = schemas.DictDetailsSimpleOut self.schema = schemas.DictDetailsSimpleOut
class TaskDal(MongoManage): class SettingsDal(DalBase):
class JobOperation(Enum): def __init__(self, db: AsyncSession):
add = "add_job" super(SettingsDal, self).__init__()
self.db = db
self.model = models.VadminSystemSettings
self.schema = schemas.SettingsSimpleOut
def __init__(self, db: AsyncIOMotorDatabase): async def get_tab_values(self, tab_id: int) -> dict:
super(TaskDal, self).__init__(db, "vadmin_system_task", schemas.TaskSimpleOut)
async def get_task(
self,
_id: str = None,
v_return_none: bool = False,
v_schema: Any = None,
**kwargs
) -> dict | None:
""" """
获取单个数据,默认使用 ID 查询,否则使用关键词查询 获取系统配置标签下的信息
包括临时字段 last_run_datetimeis_active
is_active: 只有在 scheduler_task_jobs 任务运行表中存在相同 _id 才表示任务添加成功,任务状态才为 True
last_run_datetime: 在 scheduler_task_record 中获取该任务最近一次执行完成的时间
:param _id: 数据 ID
:param v_return_none: 是否返回空 None否则抛出异常默认抛出异常
:param v_schema: 指定使用的序列化对象
""" """
if _id: datas = await self.get_datas(limit=0, tab_id=tab_id, v_return_objs=True)
kwargs["_id"] = ("ObjectId", _id) result = {}
for data in datas:
params = self.filter_condition(**kwargs) if not data.disabled:
pipeline = [ result[data.config_key] = data.config_value
{
'$addFields': {
'str_id': {'$toString': '$_id'}
}
},
{
'$lookup': {
'from': 'scheduler_task_jobs',
'localField': 'str_id',
'foreignField': '_id',
'as': 'matched_jobs'
}
},
{
'$lookup': {
'from': 'scheduler_task_record',
'localField': 'str_id',
'foreignField': 'job_id',
'as': 'matched_records'
}
},
{
'$addFields': {
'is_active': {
'$cond': {
'if': {'$ne': ['$matched_jobs', []]},
'then': True,
'else': False
}
},
'last_run_datetime': {
'$ifNull': [
{'$arrayElemAt': ['$matched_records.create_datetime', -1]},
None
]
}
}
},
{
'$business': {
'matched_records': 0,
'matched_jobs': 0
}
},
{
'$match': params
},
{
'$facet': {
'documents': [
{'$limit': 1},
]
}
}
]
# 执行聚合查询
cursor = self.collection.aggregate(pipeline)
result = await cursor.to_list(length=None)
data = result[0]['documents']
if not data and v_return_none:
return None
elif not data:
raise CustomException("未查找到对应数据", code=status.HTTP_404_NOT_FOUND)
data = data[0]
if data and v_schema:
return jsonable_encoder(v_schema(**data))
return data
async def get_tasks(
self,
page: int = 1,
limit: int = 10,
v_schema: Any = None,
v_order: str = None,
v_order_field: str = None,
**kwargs
) -> tuple:
"""
获取任务信息列表
添加了两个临时字段
is_active: 只有在 scheduler_task_jobs 任务运行表中存在相同 _id 才表示任务添加成功,任务状态才为 True
last_run_datetime: 在 scheduler_task_record 中获取该任务最近一次执行完成的时间
"""
v_order_field = v_order_field if v_order_field else 'create_datetime'
v_order = -1 if v_order in self.ORDER_FIELD else 1
params = self.filter_condition(**kwargs)
pipeline = [
{
'$addFields': {
'str_id': {'$toString': '$_id'}
}
},
{
'$lookup': {
'from': 'scheduler_task_jobs',
'localField': 'str_id',
'foreignField': '_id',
'as': 'matched_jobs'
}
},
{
'$lookup': {
'from': 'scheduler_task_record',
'localField': 'str_id',
'foreignField': 'job_id',
'as': 'matched_records'
}
},
{
'$addFields': {
'is_active': {
'$cond': {
'if': {'$ne': ['$matched_jobs', []]},
'then': True,
'else': False
}
},
'last_run_datetime': {
'$ifNull': [
{'$arrayElemAt': ['$matched_records.create_datetime', -1]},
None
]
}
}
},
{
'$business': {
'matched_records': 0,
'matched_jobs': 0
}
},
{
'$match': params
},
{
'$facet': {
'documents': [
{'$sort': {v_order_field: v_order}},
{'$limit': limit},
{'$skip': (page - 1) * limit}
],
'count': [{'$count': 'total'}]
}
}
]
# 执行聚合查询
cursor = self.collection.aggregate(pipeline)
result = await cursor.to_list(length=None)
datas = result[0]['documents']
count = result[0]['count'][0]['total'] if result[0]['count'] else 0
if count == 0:
return [], 0
elif v_schema:
datas = [jsonable_encoder(v_schema(**data)) for data in datas]
elif self.schema:
datas = [jsonable_encoder(self.schema(**data)) for data in datas]
return datas, count
async def add_task(self, rd: Redis, data: dict) -> int:
"""
添加任务到消息队列
使用消息无保留策略:无保留是指当发送者向某个频道发送消息时,如果没有订阅该频道的调用方,就直接将该消息丢弃。
:param rd: redis 对象
:param data: 行数据字典
:return: 接收到消息的订阅者数量。
"""
exec_strategy = data.get("exec_strategy")
job_params = {
"name": data.get("_id"),
"job_class": data.get("job_class"),
"expression": data.get("expression")
}
if exec_strategy == "interval" or exec_strategy == "cron":
job_params["start_date"] = data.get("start_date")
job_params["end_date"] = data.get("end_date")
message = {
"operation": self.JobOperation.add.value,
"task": {
"exec_strategy": data.get("exec_strategy"),
"job_params": job_params
}
}
return await rd.publish(SUBSCRIBE, json.dumps(message).encode('utf-8'))
async def create_task(self, rd: Redis, data: schemas.Task) -> dict:
"""
创建任务
"""
data_dict = data.model_dump()
is_active = data_dict.pop('is_active')
insert_result = await super().create_data(data_dict)
obj = await self.get_task(insert_result.inserted_id, v_schema=schemas.TaskSimpleOut)
# 如果分组不存在则新增分组
group = await TaskGroupDal(self.db).get_data(value=data.group, v_return_none=True)
if not group:
await TaskGroupDal(self.db).create_data({"value": data.group})
result = {
"subscribe_number": 0,
"is_active": is_active
}
if is_active:
# 创建任务成功后, 如果任务状态为 True则向消息队列中发送任务
result['subscribe_number'] = await self.add_task(rd, obj)
return result return result
async def put_task(self, rd: Redis, _id: str, data: schemas.Task) -> dict: async def update_datas(self, datas: dict, request: Request) -> None:
""" """
更新任务 更新系统配置信息
更新ico图标步骤先将文件上传到本地然后点击提交后获取到文件地址将上传的新文件覆盖原有文件
原因ico图标的路径是在前端的index.html中固定的所以目前只能改变图片不改变路径
""" """
data_dict = data.model_dump() for key, value in datas.items():
is_active = data_dict.pop('is_active') if key == "web_ico":
await super(TaskDal, self).put_data(_id, data) continue
obj: dict = await self.get_task(_id, v_schema=schemas.TaskSimpleOut) elif key == "web_ico_local_path":
if not value:
continue
ico = await self.get_data(config_key="web_ico", tab_id=1)
web_ico = datas.get("web_ico")
if ico.config_value == web_ico:
continue
# 将上传的ico路径替换到static/system/favicon.ico文件
await FileManage.async_copy_file(value, os.path.join(STATIC_ROOT, "system/favicon.ico"))
sql = update(self.model).where(self.model.config_key == "web_ico").values(config_value=web_ico)
await self.db.execute(sql)
else:
sql = update(self.model).where(self.model.config_key == str(key)).values(config_value=value)
await self.db.execute(sql)
if "wx_server_app_id" in datas and REDIS_DB_ENABLE:
rd = redis_getter(request)
await rd.client().set("wx_server", json.dumps(datas))
elif "sms_access_key" in datas and REDIS_DB_ENABLE:
rd = redis_getter(request)
await rd.client().set('aliyun_sms', json.dumps(datas))
# 如果分组不存在则新增分组 async def get_base_config(self) -> dict:
group = await TaskGroupDal(self.db).get_data(value=data.group, v_return_none=True) """
if not group: 获取系统基本信息
await TaskGroupDal(self.db).create_data({"value": data.group}) """
ignore_configs = ["wx_server_app_id", "wx_server_app_secret"]
try: datas = await self.get_datas(limit=0, tab_id=("in", ["1", "9"]), disabled=False, v_return_objs=True)
# 删除正在运行中的 Job result = {}
await SchedulerTaskJobsDal(self.db).delete_data(_id) for config in datas:
except CustomException as e: if config.config_key not in ignore_configs:
pass result[config.config_key] = config.config_value
result = {
"subscribe_number": 0,
"is_active": is_active
}
if is_active:
# 更新任务成功后, 如果任务状态为 True则向消息队列中发送任务
result['subscribe_number'] = await self.add_task(rd, obj)
return result return result
async def delete_task(self, _id: str) -> bool:
"""
删除任务
"""
result = await super(TaskDal, self).delete_data(_id)
try: class SettingsTabDal(DalBase):
# 删除正在运行中的 Job
await SchedulerTaskJobsDal(self.db).delete_data(_id)
except CustomException as e:
pass
return result
async def run_once_task(self, rd: Redis, _id: str) -> int: def __init__(self, db: AsyncSession):
super(SettingsTabDal, self).__init__(db, models.VadminSystemSettingsTab, schemas.SettingsTabSimpleOut)
async def get_classify_tab_values(self, classify: list[str], hidden: bool | None = False) -> dict:
""" """
执行一次任务 获取系统配置分类下的标签信息
""" """
obj: dict = await self.get_data(_id, v_schema=schemas.TaskSimpleOut) model = models.VadminSystemSettingsTab
message = { options = [joinedload(model.settings)]
"operation": self.JobOperation.add.value, datas = await self.get_datas(
"task": { limit=0,
"exec_strategy": "once", v_options=options,
"job_params": { classify=("in", classify),
"name": obj.get("_id"), disabled=False,
"job_class": obj.get("job_class") v_return_objs=True,
} hidden=hidden
)
return self.__generate_values(datas)
async def get_tab_name_values(self, tab_names: list[str], hidden: bool | None = False) -> dict:
"""
获取系统配置标签下的标签信息
"""
model = models.VadminSystemSettingsTab
options = [joinedload(model.settings)]
datas = await self.get_datas(
limit=0,
v_options=options,
tab_name=("in", tab_names),
disabled=False,
v_return_objs=True,
hidden=hidden
)
return self.__generate_values(datas)
@classmethod
def __generate_values(cls, datas: list[models.VadminSystemSettingsTab]) -> dict:
"""
生成字典值
"""
return {
tab.tab_name: {
item.config_key: item.config_value
for item in tab.settings
if not item.disabled
} }
for tab in datas
} }
return await rd.publish(SUBSCRIBE, json.dumps(message).encode('utf-8'))
class TaskGroupDal(MongoManage):
def __init__(self, db: AsyncIOMotorDatabase):
super(TaskGroupDal, self).__init__(db, "vadmin_system_task_group")
class TaskRecordDal(MongoManage):
def __init__(self, db: AsyncIOMotorDatabase):
super(TaskRecordDal, self).__init__(db, "scheduler_task_record")
class SchedulerTaskJobsDal(MongoManage):
def __init__(self, db: AsyncIOMotorDatabase):
super(SchedulerTaskJobsDal, self).__init__(db, "scheduler_task_jobs", is_object_id=False)

View File

@ -1 +1,2 @@
from .dict import VadminDictType, VadminDictDetails from .dict import VadminDictType, VadminDictDetails
from .settings import VadminSystemSettings, VadminSystemSettingsTab

View File

@ -0,0 +1,42 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# @version : 1.0
# @Create Time : 2022/7/7 13:41
# @File : settings.py
# @IDE : PyCharm
# @desc : 系统字典模型
from sqlalchemy.orm import relationship, Mapped, mapped_column
from db.db_base import BaseModel
from sqlalchemy import String, Integer, ForeignKey, Boolean, Text
class VadminSystemSettingsTab(BaseModel):
__tablename__ = "vadmin_system_settings_tab"
__table_args__ = ({'comment': '系统配置分类表'})
title: Mapped[str] = mapped_column(String(255), comment="标题")
classify: Mapped[str] = mapped_column(String(255), index=True, nullable=False, comment="分类键")
tab_label: Mapped[str] = mapped_column(String(255), comment="tab标题")
tab_name: Mapped[str] = mapped_column(String(255), index=True, nullable=False, unique=True, comment="tab标识符")
hidden: Mapped[bool] = mapped_column(Boolean, default=False, comment="是否隐藏")
disabled: Mapped[bool] = mapped_column(Boolean, default=False, comment="是否禁用")
settings: Mapped[list["VadminSystemSettings"]] = relationship(back_populates="tab")
class VadminSystemSettings(BaseModel):
__tablename__ = "vadmin_system_settings"
__table_args__ = ({'comment': '系统配置表'})
config_label: Mapped[str] = mapped_column(String(255), comment="配置表标签")
config_key: Mapped[str] = mapped_column(String(255), index=True, nullable=False, unique=True, comment="配置表键")
config_value: Mapped[str | None] = mapped_column(Text, comment="配置表内容")
remark: Mapped[str | None] = mapped_column(String(255), comment="备注信息")
disabled: Mapped[bool] = mapped_column(Boolean, default=False, comment="是否禁用")
tab_id: Mapped[int] = mapped_column(
Integer,
ForeignKey("vadmin_system_settings_tab.id", ondelete='CASCADE'),
comment="关联tab标签"
)
tab: Mapped[VadminSystemSettingsTab] = relationship(foreign_keys=tab_id, back_populates="settings")

View File

@ -1,3 +1,2 @@
from .dict_type import DictTypeParams from .dict_type import DictTypeParams
from .dict_detail import DictDetailParams from .dict_detail import DictDetailParams
from .task import TaskParams

View File

@ -1,32 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# @version : 1.0
# @Create Time : 2023/6/25 14:50
# @File : task.py
# @IDE : PyCharm
# @desc : 简要说明
from fastapi import Depends
from core.dependencies import Paging, QueryParams
class TaskParams(QueryParams):
"""
列表分页
"""
def __init__(self, name: str = None, _id: str = None, group: str = None, params: Paging = Depends()):
super().__init__(params)
self.name = ("like", name)
self.group = group
self._id = ("ObjectId", _id)
self.v_order = "desc"
class TaskRecordParams(QueryParams):
"""
列表分页
"""
def __init__(self, job_id: str = None, name: str = None, params: Paging = Depends()):
super().__init__(params)
self.job_id = ("like", job_id)
self.name = ("like", name)
self.v_order = "desc"

View File

@ -1,2 +1,3 @@
from .dict import DictType, DictDetails, DictTypeSimpleOut, DictDetailsSimpleOut, DictTypeOptionsOut from .dict import DictType, DictDetails, DictTypeSimpleOut, DictDetailsSimpleOut, DictTypeOptionsOut
from .task import Task, TaskSimpleOut from .settings_tab import SettingsTab, SettingsTabSimpleOut
from .settings import Settings, SettingsSimpleOut

View File

@ -0,0 +1,29 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# @version : 1.0
# @Create Time : 2021/10/18 22:19
# @File : settings.py
# @IDE : PyCharm
# @desc : pydantic 模型,用于数据库序列化操作
from pydantic import BaseModel, ConfigDict
from core.data_types import DatetimeStr
class Settings(BaseModel):
config_label: str | None = None
config_key: str
config_value: str | None = None
remark: str | None = None
disabled: bool | None = None
tab_id: int
class SettingsSimpleOut(Settings):
model_config = ConfigDict(from_attributes=True)
id: int
create_datetime: DatetimeStr
update_datetime: DatetimeStr

View File

@ -0,0 +1,28 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# @version : 1.0
# @Create Time : 2021/10/18 22:19
# @File : settings_tab.py
# @IDE : PyCharm
# @desc : pydantic 模型,用于数据库序列化操作
from pydantic import BaseModel, ConfigDict
from core.data_types import DatetimeStr
class SettingsTab(BaseModel):
title: str
classify: str
tab_label: str
tab_name: str
hidden: bool
class SettingsTabSimpleOut(SettingsTab):
model_config = ConfigDict(from_attributes=True)
id: int
create_datetime: DatetimeStr
update_datetime: DatetimeStr

View File

@ -1,32 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# @version : 1.0
# @Create Time : 2023/6/25 15:08
# @File : task.py
# @IDE : PyCharm
# @desc : 简要说明
from pydantic import BaseModel, Field, ConfigDict
from core.data_types import DatetimeStr, ObjectIdStr
class Task(BaseModel):
name: str
group: str | None = None
job_class: str
exec_strategy: str
expression: str
is_active: bool | None = True # 临时字段,不在表中创建
remark: str | None = None
start_date: DatetimeStr | None = None
end_date: DatetimeStr | None = None
class TaskSimpleOut(Task):
model_config = ConfigDict(from_attributes=True)
id: ObjectIdStr = Field(..., alias='_id')
create_datetime: DatetimeStr
update_datetime: DatetimeStr
last_run_datetime: DatetimeStr | None = None # 临时字段,不在表中创建

View File

@ -5,19 +5,16 @@
# @IDE : PyCharm # @IDE : PyCharm
# @desc : 主要接口文件 # @desc : 主要接口文件
from redis.asyncio import Redis from fastapi import APIRouter, Depends, Body, Request
from fastapi import APIRouter, Depends, Body from sqlalchemy.ext.asyncio import AsyncSession
from motor.motor_asyncio import AsyncIOMotorDatabase from core.database import db_getter
from core.database import redis_getter, mongo_getter from utils.response import SuccessResponse
from utils.response import SuccessResponse, ErrorResponse
from utils.sms.code import CodeSMS
from . import schemas, crud from . import schemas, crud
from core.dependencies import IdList from core.dependencies import IdList
from apps.vadmin.auth.utils.current import AllUserAuth, OpenAuth from apps.vadmin.auth.utils.current import AllUserAuth, FullAdminAuth, OpenAuth
from apps.vadmin.auth.utils.validation.auth import Auth from apps.vadmin.auth.utils.validation.auth import Auth
from .params import DictTypeParams, DictDetailParams, TaskParams from .params import DictTypeParams, DictDetailParams
from apps.vadmin.auth import crud as vadmin_auth_crud
from .params.task import TaskRecordParams
app = APIRouter() app = APIRouter()
@ -99,96 +96,39 @@ async def get_dict_detail(data_id: int, auth: Auth = Depends(AllUserAuth())):
########################################################### ###########################################################
# 短信服务管理 # 系统配置管理
########################################################### ###########################################################
@app.post("/sms/send", summary="发送短信验证码(阿里云服务)") @app.post("/settings/tabs", summary="获取系统配置标签列表")
async def sms_send(telephone: str, rd: Redis = Depends(redis_getter), auth: Auth = Depends(OpenAuth())): async def get_settings_tabs(classifys: list[str] = Body(...), auth: Auth = Depends(FullAdminAuth())):
user = await vadmin_auth_crud.UserDal(auth.db).get_data(telephone=telephone, v_return_none=True) return SuccessResponse(await crud.SettingsTabDal(auth.db).get_datas(limit=0, classify=("in", classifys)))
if not user:
return ErrorResponse("手机号不存在!")
sms = CodeSMS(telephone, rd)
return SuccessResponse(await sms.main_async())
########################################################### @app.get("/settings/tabs/values", summary="获取系统配置标签下的信息")
# 定时任务管理 async def get_settings_tabs_values(tab_id: int, auth: Auth = Depends(FullAdminAuth())):
########################################################### return SuccessResponse(await crud.SettingsDal(auth.db).get_tab_values(tab_id=tab_id))
@app.get("/tasks", summary="获取定时任务列表")
async def get_tasks(
p: TaskParams = Depends(), @app.put("/settings/tabs/values", summary="更新系统配置信息")
db: AsyncIOMotorDatabase = Depends(mongo_getter), async def put_settings_tabs_values(
auth: Auth = Depends(AllUserAuth()) request: Request,
datas: dict = Body(...),
auth: Auth = Depends(FullAdminAuth())
): ):
datas, count = await crud.TaskDal(db).get_tasks(**p.dict()) return SuccessResponse(await crud.SettingsDal(auth.db).update_datas(datas, request))
return SuccessResponse(datas, count=count)
@app.post("/tasks", summary="添加定时任务") @app.get("/settings/base/config", summary="获取系统基础配置", description="每次进入系统中时使用")
async def post_tasks( async def get_setting_base_config(db: AsyncSession = Depends(db_getter)):
data: schemas.Task, return SuccessResponse(await crud.SettingsDal(db).get_base_config())
db: AsyncIOMotorDatabase = Depends(mongo_getter),
rd: Redis = Depends(redis_getter),
auth: Auth = Depends(AllUserAuth())
):
return SuccessResponse(await crud.TaskDal(db).create_task(rd, data))
@app.put("/tasks", summary="更新定时任务") @app.get("/settings/privacy", summary="获取隐私协议")
async def put_tasks( async def get_settings_privacy(auth: Auth = Depends(OpenAuth())):
_id: str, return SuccessResponse((await crud.SettingsDal(auth.db).get_data(config_key="web_privacy")).config_value)
data: schemas.Task,
db: AsyncIOMotorDatabase = Depends(mongo_getter),
rd: Redis = Depends(redis_getter),
auth: Auth = Depends(AllUserAuth())
):
return SuccessResponse(await crud.TaskDal(db).put_task(rd, _id, data))
@app.delete("/tasks", summary="删除单个定时任务") @app.get("/settings/agreement", summary="获取用户协议")
async def delete_task( async def get_settings_agreement(auth: Auth = Depends(OpenAuth())):
_id: str, return SuccessResponse((await crud.SettingsDal(auth.db).get_data(config_key="web_agreement")).config_value)
db: AsyncIOMotorDatabase = Depends(mongo_getter),
auth: Auth = Depends(AllUserAuth())
):
return SuccessResponse(await crud.TaskDal(db).delete_task(_id))
@app.get("/task", summary="获取定时任务详情")
async def get_task(
_id: str,
db: AsyncIOMotorDatabase = Depends(mongo_getter),
auth: Auth = Depends(AllUserAuth())
):
return SuccessResponse(await crud.TaskDal(db).get_task(_id, v_schema=schemas.TaskSimpleOut))
@app.post("/task", summary="执行一次定时任务")
async def run_once_task(
_id: str,
db: AsyncIOMotorDatabase = Depends(mongo_getter),
rd: Redis = Depends(redis_getter),
auth: Auth = Depends(AllUserAuth())
):
return SuccessResponse(await crud.TaskDal(db).run_once_task(rd, _id))
###########################################################
# 定时任务分组管理
###########################################################
@app.get("/task/group/options", summary="获取定时任务分组选择项列表")
async def get_task_group_options(db: AsyncIOMotorDatabase = Depends(mongo_getter), auth: Auth = Depends(AllUserAuth())):
return SuccessResponse(await crud.TaskGroupDal(db).get_datas(limit=0))
###########################################################
# 定时任务调度日志
###########################################################
@app.get("/task/records", summary="获取定时任务调度日志列表")
async def get_task_records(
p: TaskRecordParams = Depends(),
db: AsyncIOMotorDatabase = Depends(mongo_getter),
auth: Auth = Depends(AllUserAuth())
):
count = await crud.TaskRecordDal(db).get_count(**p.to_count())
datas = await crud.TaskRecordDal(db).get_datas(**p.dict())
return SuccessResponse(datas, count=count)

Binary file not shown.