From 939e29c2d670ba9b2030924bd21e39bf32778549 Mon Sep 17 00:00:00 2001 From: sunyugang Date: Wed, 7 May 2025 14:17:36 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=9B=AE=E6=A0=87=E8=BF=BD?= =?UTF-8?q?=E8=B8=AA=E7=9A=84=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/business/deepsort/service.py | 25 +- apps/business/detect/service.py | 25 +- apps/vadmin/auth/utils/validation/login.py | 2 - apps/vadmin/system/crud.py | 415 +++++---------------- apps/vadmin/system/models/__init__.py | 1 + apps/vadmin/system/models/settings.py | 42 +++ apps/vadmin/system/params/__init__.py | 3 +- apps/vadmin/system/params/task.py | 32 -- apps/vadmin/system/schemas/__init__.py | 3 +- apps/vadmin/system/schemas/settings.py | 29 ++ apps/vadmin/system/schemas/settings_tab.py | 28 ++ apps/vadmin/system/schemas/task.py | 32 -- apps/vadmin/system/views.py | 122 ++---- requirements.txt | Bin 4864 -> 4888 bytes 14 files changed, 256 insertions(+), 503 deletions(-) create mode 100644 apps/vadmin/system/models/settings.py delete mode 100644 apps/vadmin/system/params/task.py create mode 100644 apps/vadmin/system/schemas/settings.py create mode 100644 apps/vadmin/system/schemas/settings_tab.py delete mode 100644 apps/vadmin/system/schemas/task.py diff --git a/apps/business/deepsort/service.py b/apps/business/deepsort/service.py index 35bd87d..0378509 100644 --- a/apps/business/deepsort/service.py +++ b/apps/business/deepsort/service.py @@ -6,7 +6,7 @@ import torch from utils.yolov5.models.common import DetectMultiBackend from utils.yolov5.utils.torch_utils import select_device 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.utils.draw import draw_boxes @@ -69,22 +69,17 @@ async def run_deepsort( time.sleep(2) # 等待2s,等待websocket进入 - dt = (Profile(device=device), Profile(device=device), Profile(device=device)) - for path, im, im0s, vid_cap, s in dataset: if room_manager.rooms.get(room): - with dt[0]: - im0 = im0s[0] - im = torch.from_numpy(im).to(model.device) - im = im.half() if model.fp16 else im.float() # uint8 to fp16/32 - im /= 255 # 0 - 255 to 0.0 - 1.0 - if len(im.shape) == 3: - im = im[None] # expand for batch dim - with dt[1]: - pred = model(im, augment=False, visualize=False) - with dt[2]: - # NMS - pred = non_max_suppression(pred, 0.25, 0.45, None, False, max_det=1000)[0] + im0 = im0s[0] + im = torch.from_numpy(im).to(model.device) + im = im.half() if model.fp16 else im.float() # uint8 to fp16/32 + im /= 255 # 0 - 255 to 0.0 - 1.0 + if len(im.shape) == 3: + im = im[None] # expand for batch dim + pred = model(im, augment=False, visualize=False) + # 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() diff --git a/apps/business/detect/service.py b/apps/business/detect/service.py index 1956786..d39b88f 100644 --- a/apps/business/detect/service.py +++ b/apps/business/detect/service.py @@ -8,7 +8,7 @@ from utils.yolov5.utils.torch_utils import select_device from ultralytics.utils.plotting import Annotator, colors from utils.yolov5.models.common import DetectMultiBackend 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 torch @@ -97,7 +97,7 @@ async def run_detect_img( room = 'detect_' + str(detect_id) await room_manager.send_to_room(room, f"AiCheck: 模型训练开始,请稍等。。。\n") 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版本 if is_gpu == 'True': 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)) - dt = (Profile(device=device), Profile(device=device), Profile(device=device)) - - time.sleep(3) # 等待2s,等待websocket进入 + time.sleep(3) # 等待3s,等待websocket进入 for path, im, im0s, vid_cap, s in dataset: if room_manager.rooms.get(room): - with dt[0]: - im = torch.from_numpy(im).to(model.device) - im = im.half() if model.fp16 else im.float() # uint8 to fp16/32 - im /= 255 # 0 - 255 to 0.0 - 1.0 - if len(im.shape) == 3: - im = im[None] # expand for batch dim + im = torch.from_numpy(im).to(model.device) + im = im.half() if model.fp16 else im.float() # uint8 to fp16/32 + im /= 255 # 0 - 255 to 0.0 - 1.0 + if len(im.shape) == 3: + im = im[None] # expand for batch dim # Inference - with dt[1]: - pred = model(im, augment=False, visualize=False) + pred = model(im, augment=False, visualize=False) # 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 for i, det in enumerate(pred): # per image diff --git a/apps/vadmin/auth/utils/validation/login.py b/apps/vadmin/auth/utils/validation/login.py index 424962c..029ce00 100644 --- a/apps/vadmin/auth/utils/validation/login.py +++ b/apps/vadmin/auth/utils/validation/login.py @@ -80,8 +80,6 @@ class LoginValidation: await db.flush() elif not user.is_active: self.result.msg = "此手机号已被冻结!" - elif data.platform in ["0", "1"]: - self.result.msg = "此手机号无权限!" else: if not DEMO and count: await count.delete() diff --git a/apps/vadmin/system/crud.py b/apps/vadmin/system/crud.py index cffbe93..e470d35 100644 --- a/apps/vadmin/system/crud.py +++ b/apps/vadmin/system/crud.py @@ -7,20 +7,16 @@ # @desc : 数据库 增删改查操作 import json -from enum import Enum -from typing import Any -from redis.asyncio import Redis -from fastapi.encoders import jsonable_encoder -from motor.motor_asyncio import AsyncIOMotorDatabase -from sqlalchemy import select +import os +from sqlalchemy import select, update from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import joinedload -from application.settings import SUBSCRIBE -from core.mongo_manage import MongoManage +from application.settings import STATIC_ROOT, REDIS_DB_ENABLE +from core.database import redis_getter +from utils.file.file_manage import FileManage from . import models, schemas from core.crud import DalBase -from core.exception import CustomException -from utils import status +from fastapi import Request class DictTypeDal(DalBase): @@ -67,323 +63,116 @@ class DictDetailsDal(DalBase): self.schema = schemas.DictDetailsSimpleOut -class TaskDal(MongoManage): +class SettingsDal(DalBase): - class JobOperation(Enum): - add = "add_job" + def __init__(self, db: AsyncSession): + super(SettingsDal, self).__init__() + self.db = db + self.model = models.VadminSystemSettings + self.schema = schemas.SettingsSimpleOut - def __init__(self, db: AsyncIOMotorDatabase): - 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: + async def get_tab_values(self, tab_id: int) -> dict: """ - 获取单个数据,默认使用 ID 查询,否则使用关键词查询 - - 包括临时字段 last_run_datetime,is_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: - kwargs["_id"] = ("ObjectId", _id) - - 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': [ - {'$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) + datas = await self.get_datas(limit=0, tab_id=tab_id, v_return_objs=True) + result = {} + for data in datas: + if not data.disabled: + result[data.config_key] = data.config_value 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() - is_active = data_dict.pop('is_active') - await super(TaskDal, self).put_data(_id, data) - obj: dict = await self.get_task(_id, v_schema=schemas.TaskSimpleOut) + for key, value in datas.items(): + if key == "web_ico": + continue + 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)) - # 如果分组不存在则新增分组 - 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}) - - try: - # 删除正在运行中的 Job - await SchedulerTaskJobsDal(self.db).delete_data(_id) - except CustomException as e: - pass - - result = { - "subscribe_number": 0, - "is_active": is_active - } - - if is_active: - # 更新任务成功后, 如果任务状态为 True,则向消息队列中发送任务 - result['subscribe_number'] = await self.add_task(rd, obj) + async def get_base_config(self) -> dict: + """ + 获取系统基本信息 + """ + ignore_configs = ["wx_server_app_id", "wx_server_app_secret"] + datas = await self.get_datas(limit=0, tab_id=("in", ["1", "9"]), disabled=False, v_return_objs=True) + result = {} + for config in datas: + if config.config_key not in ignore_configs: + result[config.config_key] = config.config_value return result - async def delete_task(self, _id: str) -> bool: - """ - 删除任务 - """ - result = await super(TaskDal, self).delete_data(_id) - try: - # 删除正在运行中的 Job - await SchedulerTaskJobsDal(self.db).delete_data(_id) - except CustomException as e: - pass - return result +class SettingsTabDal(DalBase): - 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) - message = { - "operation": self.JobOperation.add.value, - "task": { - "exec_strategy": "once", - "job_params": { - "name": obj.get("_id"), - "job_class": obj.get("job_class") - } + model = models.VadminSystemSettingsTab + options = [joinedload(model.settings)] + datas = await self.get_datas( + limit=0, + v_options=options, + classify=("in", classify), + disabled=False, + 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) diff --git a/apps/vadmin/system/models/__init__.py b/apps/vadmin/system/models/__init__.py index 8ff9a44..c18b7be 100644 --- a/apps/vadmin/system/models/__init__.py +++ b/apps/vadmin/system/models/__init__.py @@ -1 +1,2 @@ from .dict import VadminDictType, VadminDictDetails +from .settings import VadminSystemSettings, VadminSystemSettingsTab diff --git a/apps/vadmin/system/models/settings.py b/apps/vadmin/system/models/settings.py new file mode 100644 index 0000000..f2f083a --- /dev/null +++ b/apps/vadmin/system/models/settings.py @@ -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") diff --git a/apps/vadmin/system/params/__init__.py b/apps/vadmin/system/params/__init__.py index ffe40d8..ea7a3ed 100644 --- a/apps/vadmin/system/params/__init__.py +++ b/apps/vadmin/system/params/__init__.py @@ -1,3 +1,2 @@ from .dict_type import DictTypeParams -from .dict_detail import DictDetailParams -from .task import TaskParams +from .dict_detail import DictDetailParams \ No newline at end of file diff --git a/apps/vadmin/system/params/task.py b/apps/vadmin/system/params/task.py deleted file mode 100644 index b561318..0000000 --- a/apps/vadmin/system/params/task.py +++ /dev/null @@ -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" diff --git a/apps/vadmin/system/schemas/__init__.py b/apps/vadmin/system/schemas/__init__.py index 9744247..98cf676 100644 --- a/apps/vadmin/system/schemas/__init__.py +++ b/apps/vadmin/system/schemas/__init__.py @@ -1,2 +1,3 @@ from .dict import DictType, DictDetails, DictTypeSimpleOut, DictDetailsSimpleOut, DictTypeOptionsOut -from .task import Task, TaskSimpleOut +from .settings_tab import SettingsTab, SettingsTabSimpleOut +from .settings import Settings, SettingsSimpleOut diff --git a/apps/vadmin/system/schemas/settings.py b/apps/vadmin/system/schemas/settings.py new file mode 100644 index 0000000..775d59d --- /dev/null +++ b/apps/vadmin/system/schemas/settings.py @@ -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 + diff --git a/apps/vadmin/system/schemas/settings_tab.py b/apps/vadmin/system/schemas/settings_tab.py new file mode 100644 index 0000000..fd8a9f2 --- /dev/null +++ b/apps/vadmin/system/schemas/settings_tab.py @@ -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 + diff --git a/apps/vadmin/system/schemas/task.py b/apps/vadmin/system/schemas/task.py deleted file mode 100644 index 774085c..0000000 --- a/apps/vadmin/system/schemas/task.py +++ /dev/null @@ -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 # 临时字段,不在表中创建 - diff --git a/apps/vadmin/system/views.py b/apps/vadmin/system/views.py index 1fe09b0..b97c2ed 100644 --- a/apps/vadmin/system/views.py +++ b/apps/vadmin/system/views.py @@ -5,19 +5,16 @@ # @IDE : PyCharm # @desc : 主要接口文件 -from redis.asyncio import Redis -from fastapi import APIRouter, Depends, Body -from motor.motor_asyncio import AsyncIOMotorDatabase -from core.database import redis_getter, mongo_getter -from utils.response import SuccessResponse, ErrorResponse -from utils.sms.code import CodeSMS +from fastapi import APIRouter, Depends, Body, Request +from sqlalchemy.ext.asyncio import AsyncSession +from core.database import db_getter +from utils.response import SuccessResponse from . import schemas, crud 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 .params import DictTypeParams, DictDetailParams, TaskParams -from apps.vadmin.auth import crud as vadmin_auth_crud -from .params.task import TaskRecordParams +from .params import DictTypeParams, DictDetailParams + app = APIRouter() @@ -99,96 +96,39 @@ async def get_dict_detail(data_id: int, auth: Auth = Depends(AllUserAuth())): ########################################################### -# 短信服务管理 +# 系统配置管理 ########################################################### -@app.post("/sms/send", summary="发送短信验证码(阿里云服务)") -async def sms_send(telephone: str, rd: Redis = Depends(redis_getter), auth: Auth = Depends(OpenAuth())): - user = await vadmin_auth_crud.UserDal(auth.db).get_data(telephone=telephone, v_return_none=True) - if not user: - return ErrorResponse("手机号不存在!") - sms = CodeSMS(telephone, rd) - return SuccessResponse(await sms.main_async()) +@app.post("/settings/tabs", summary="获取系统配置标签列表") +async def get_settings_tabs(classifys: list[str] = Body(...), auth: Auth = Depends(FullAdminAuth())): + return SuccessResponse(await crud.SettingsTabDal(auth.db).get_datas(limit=0, classify=("in", classifys))) -########################################################### -# 定时任务管理 -########################################################### -@app.get("/tasks", summary="获取定时任务列表") -async def get_tasks( - p: TaskParams = Depends(), - db: AsyncIOMotorDatabase = Depends(mongo_getter), - auth: Auth = Depends(AllUserAuth()) +@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.put("/settings/tabs/values", summary="更新系统配置信息") +async def put_settings_tabs_values( + request: Request, + datas: dict = Body(...), + auth: Auth = Depends(FullAdminAuth()) ): - datas, count = await crud.TaskDal(db).get_tasks(**p.dict()) - return SuccessResponse(datas, count=count) + return SuccessResponse(await crud.SettingsDal(auth.db).update_datas(datas, request)) -@app.post("/tasks", summary="添加定时任务") -async def post_tasks( - data: schemas.Task, - 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.get("/settings/base/config", summary="获取系统基础配置", description="每次进入系统中时使用") +async def get_setting_base_config(db: AsyncSession = Depends(db_getter)): + return SuccessResponse(await crud.SettingsDal(db).get_base_config()) -@app.put("/tasks", summary="更新定时任务") -async def put_tasks( - _id: str, - 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.get("/settings/privacy", summary="获取隐私协议") +async def get_settings_privacy(auth: Auth = Depends(OpenAuth())): + return SuccessResponse((await crud.SettingsDal(auth.db).get_data(config_key="web_privacy")).config_value) -@app.delete("/tasks", summary="删除单个定时任务") -async def delete_task( - _id: str, - db: AsyncIOMotorDatabase = Depends(mongo_getter), - auth: Auth = Depends(AllUserAuth()) -): - return SuccessResponse(await crud.TaskDal(db).delete_task(_id)) +@app.get("/settings/agreement", summary="获取用户协议") +async def get_settings_agreement(auth: Auth = Depends(OpenAuth())): + return SuccessResponse((await crud.SettingsDal(auth.db).get_data(config_key="web_agreement")).config_value) -@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) diff --git a/requirements.txt b/requirements.txt index bee79fb8f5d589068e629b4cf87416ab95a778c4..dc25df789245535db855f9c78e4b21e71c4574d5 100644 GIT binary patch delta 34 ocmZoro1wO03%{r~g91YeLn;s!FvK$yGvqTAF_diH$nVb#0GzrA!T