AI实验室后端
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
from .aimessage import *
|
||||
from .aiprofile import *
|
||||
from .aisession import *
|
||||
from .annual_meeting import *
|
||||
from .image_ysa import *
|
||||
from .iot import *
|
||||
from .knowledge import *
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
from uuid import UUID
|
||||
|
||||
from config.minIO import get_temp_url
|
||||
from config.pgDb import pg_pool
|
||||
from utils import format_datetime
|
||||
|
||||
|
||||
def get_all_exchange_records():
|
||||
"""获取 annual_meeting_exchange 表所有记录"""
|
||||
with pg_pool.getConn() as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
"""
|
||||
SELECT id, gift_code, name, created_at, is_finished, sort
|
||||
FROM annual_meeting_exchange
|
||||
ORDER BY sort
|
||||
"""
|
||||
)
|
||||
rows = cur.fetchall()
|
||||
return [
|
||||
{
|
||||
"id": row[0],
|
||||
"gift_code": row[1],
|
||||
"name": row[2],
|
||||
"created_at": row[3],
|
||||
"is_finished": row[4],
|
||||
"sort": row[5],
|
||||
}
|
||||
for row in rows
|
||||
]
|
||||
|
||||
|
||||
import random
|
||||
import time
|
||||
|
||||
|
||||
def reset_all_exchange_status():
|
||||
"""将所有记录 is_finished 置为 False,并随机 position(以当前时间作为随机种子)"""
|
||||
with pg_pool.getConn() as conn:
|
||||
with conn.cursor() as cur:
|
||||
# 获取总记录数
|
||||
cur.execute("SELECT id FROM annual_meeting_exchange")
|
||||
ids = [row[0] for row in cur.fetchall()]
|
||||
|
||||
# 用当前时间戳作为随机种子
|
||||
seed = int(time.time() * 1000) # 毫秒级
|
||||
random.seed(seed)
|
||||
|
||||
# 生成随机顺序的 position
|
||||
positions = list(range(1, len(ids) + 1))
|
||||
random.shuffle(positions)
|
||||
|
||||
# 更新每条记录
|
||||
for record_id, pos in zip(ids, positions):
|
||||
cur.execute(
|
||||
"""
|
||||
UPDATE annual_meeting_exchange
|
||||
SET is_finished = FALSE, sort = %s
|
||||
WHERE id = %s
|
||||
""",
|
||||
(pos, record_id),
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
return {"updated_count": len(ids), "seed_used": seed}
|
||||
|
||||
|
||||
def reset_user_status(target_user_id: str):
|
||||
"""重置指定用户的 is_finished"""
|
||||
with pg_pool.getConn() as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
"""
|
||||
UPDATE annual_meeting_exchange
|
||||
SET is_finished = True
|
||||
WHERE id = %s
|
||||
""",
|
||||
(target_user_id,),
|
||||
)
|
||||
conn.commit()
|
||||
return {"updated": cur.rowcount}
|
||||
|
||||
|
||||
def get_all_lottery():
|
||||
"""获取 annual_meeting_lottery 全部数据"""
|
||||
with pg_pool.getConn() as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
"""
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
is_opened,
|
||||
oss,
|
||||
created_at,
|
||||
remark,
|
||||
sort
|
||||
FROM annual_meeting_lottery
|
||||
ORDER BY sort ASC
|
||||
"""
|
||||
)
|
||||
rows = cur.fetchall()
|
||||
|
||||
return [
|
||||
{
|
||||
"id": row[0],
|
||||
"name": row[1],
|
||||
"is_opened": 1 if row[2] else 0,
|
||||
"oss_url": get_temp_url("image-annual-lottery", row[3]),
|
||||
"created_at": format_datetime(row[4]),
|
||||
"remark": row[5],
|
||||
"sort": row[6],
|
||||
}
|
||||
for row in rows
|
||||
]
|
||||
|
||||
|
||||
def add_lottery(name: str, sort: int, oss: str, is_opened: bool, remark: str):
|
||||
"""新增礼品"""
|
||||
with pg_pool.getConn() as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
"""
|
||||
INSERT INTO annual_meeting_lottery
|
||||
(id, name, sort, oss, is_opened, remark, created_at)
|
||||
VALUES (gen_random_uuid(), %s, %s, %s, %s, %s, now())
|
||||
RETURNING id
|
||||
""",
|
||||
(name, sort, oss, is_opened, remark),
|
||||
)
|
||||
new_id = cur.fetchone()[0]
|
||||
conn.commit()
|
||||
return {"id": new_id}
|
||||
|
||||
|
||||
def update_lottery(
|
||||
id: str,
|
||||
name: str = None,
|
||||
sort: int = None,
|
||||
oss: str = None,
|
||||
is_opened: bool = None,
|
||||
remark: str = None,
|
||||
):
|
||||
"""更新礼品信息"""
|
||||
update_fields = []
|
||||
params = []
|
||||
|
||||
if name is not None:
|
||||
update_fields.append("name = %s")
|
||||
params.append(name)
|
||||
if sort is not None:
|
||||
update_fields.append("sort = %s")
|
||||
params.append(sort)
|
||||
if oss is not None:
|
||||
update_fields.append("oss = %s")
|
||||
params.append(oss)
|
||||
if is_opened is not None:
|
||||
update_fields.append("is_opened = %s")
|
||||
params.append(is_opened)
|
||||
if remark is not None:
|
||||
update_fields.append("remark = %s")
|
||||
params.append(remark)
|
||||
|
||||
if not update_fields:
|
||||
return {"updated": 0}
|
||||
|
||||
params.append(id)
|
||||
|
||||
sql = f"""
|
||||
UPDATE annual_meeting_lottery
|
||||
SET {", ".join(update_fields)}
|
||||
WHERE id = %s
|
||||
"""
|
||||
|
||||
with pg_pool.getConn() as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(sql, tuple(params))
|
||||
conn.commit()
|
||||
return {"updated": cur.rowcount}
|
||||
|
||||
|
||||
def delete_lottery(id: str):
|
||||
"""删除礼品"""
|
||||
with pg_pool.getConn() as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
"""
|
||||
DELETE FROM annual_meeting_lottery
|
||||
WHERE id = %s
|
||||
""",
|
||||
(id,),
|
||||
)
|
||||
conn.commit()
|
||||
return {"deleted": cur.rowcount}
|
||||
|
||||
|
||||
def reset_lottery_item(item_id: UUID):
|
||||
"""将单个奖品标记为已开启"""
|
||||
with pg_pool.getConn() as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
"""
|
||||
UPDATE annual_meeting_lottery
|
||||
SET is_opened = TRUE
|
||||
WHERE id = %s
|
||||
""",
|
||||
(item_id,),
|
||||
)
|
||||
conn.commit()
|
||||
return cur.rowcount
|
||||
|
||||
|
||||
def reset_all_lottery_db():
|
||||
"""将所有奖品 is_opened 置为 False"""
|
||||
with pg_pool.getConn() as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
"""
|
||||
UPDATE annual_meeting_lottery
|
||||
SET is_opened = FALSE
|
||||
"""
|
||||
)
|
||||
conn.commit()
|
||||
return cur.rowcount
|
||||
@@ -157,10 +157,11 @@ def update_device_db(id: str, data: dict) -> int:
|
||||
cursor.execute(
|
||||
"""
|
||||
UPDATE iot_users
|
||||
SET remark=%s, is_active=%s, dept_id=%s, is_superuser=%s
|
||||
SET name=%s, remark=%s, is_active=%s, dept_id=%s, is_superuser=%s
|
||||
WHERE id=%s;
|
||||
""",
|
||||
(
|
||||
data.get("name"),
|
||||
data.get("remark"),
|
||||
bool(data.get("status", 1)),
|
||||
data.get("dept_id"),
|
||||
|
||||
@@ -149,6 +149,77 @@ def get_sentinel_record_list_db_page(
|
||||
return result, total
|
||||
|
||||
|
||||
def get_sentinel_record_by_id(record_id):
|
||||
if not record_id:
|
||||
return None
|
||||
|
||||
sql = """
|
||||
SELECT
|
||||
r.id,
|
||||
r.license_plate,
|
||||
r.vehicle_type,
|
||||
r.license_plate_image,
|
||||
r.vehicle_image,
|
||||
r.livestock_type,
|
||||
r.livestock_source,
|
||||
r.is_inspected,
|
||||
r.dept_id,
|
||||
sd.name AS dept_name,
|
||||
r.created_at,
|
||||
r.updated_at,
|
||||
r.remark
|
||||
FROM sentinel_records r
|
||||
LEFT JOIN sys_dept sd ON r.dept_id = sd.id
|
||||
WHERE r.id = %s;
|
||||
"""
|
||||
|
||||
with pg_pool.getConn() as conn:
|
||||
with conn.cursor() as cursor:
|
||||
cursor.execute(sql, [record_id])
|
||||
row = cursor.fetchone()
|
||||
|
||||
if not row:
|
||||
return None
|
||||
|
||||
(
|
||||
record_id,
|
||||
license_plate,
|
||||
vehicle_type,
|
||||
license_plate_image,
|
||||
vehicle_image,
|
||||
livestock_type,
|
||||
livestock_source,
|
||||
is_inspected,
|
||||
dept_id,
|
||||
dept_name,
|
||||
created_at,
|
||||
updated_at,
|
||||
remark,
|
||||
) = row
|
||||
|
||||
result = {
|
||||
"id": str(record_id),
|
||||
"license_plate": license_plate,
|
||||
"vehicle_type": vehicle_type,
|
||||
"license_plate_image": get_temp_url_dict(
|
||||
"sentinel", "license_plate", license_plate_image
|
||||
),
|
||||
"vehicle_image": get_temp_url_dict(
|
||||
"sentinel", "vehicle_image", vehicle_image
|
||||
),
|
||||
"livestock_type": livestock_type,
|
||||
"livestock_source": livestock_source,
|
||||
"is_inspected": 1 if is_inspected else 0,
|
||||
"dept_id": str(dept_id),
|
||||
"dept_name": dept_name,
|
||||
"created_at": format_datetime(created_at),
|
||||
"updated_at": format_datetime(updated_at),
|
||||
"remark": remark,
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def insert_sentinel_record(data: dict, dept_id) -> str:
|
||||
with pg_pool.getConn() as conn:
|
||||
with conn.cursor() as cursor:
|
||||
|
||||
@@ -583,6 +583,7 @@ def patch_user_db(id: str, data: dict) -> int:
|
||||
sql = f"UPDATE sys_users SET {', '.join(fields)} WHERE id = %s"
|
||||
params.append(id)
|
||||
cursor.execute(sql, tuple(params))
|
||||
updated_count = cursor.rowcount # 保存这次的结果
|
||||
|
||||
# ------------------------
|
||||
# 2. roles 单独处理
|
||||
@@ -597,7 +598,7 @@ def patch_user_db(id: str, data: dict) -> int:
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
return cursor.rowcount
|
||||
return updated_count
|
||||
|
||||
|
||||
# 删除用户
|
||||
@@ -954,14 +955,24 @@ def get_dept_id_by_user_id(user_id: str) -> str:
|
||||
return str(dept_id)
|
||||
|
||||
|
||||
def get_dept_name_by_dept_id(user_id: str) -> str:
|
||||
with pg_pool.getConn() as conn:
|
||||
with conn.cursor() as cursor:
|
||||
cursor.execute("SELECT name FROM sys_dept WHERE id = %s", (user_id,))
|
||||
dept_id = cursor.fetchone()
|
||||
dept_id = dept_id[0]
|
||||
return str(dept_id)
|
||||
|
||||
|
||||
def get_dept_id_by_iot_user_name(user_id: str) -> str:
|
||||
# 通过 iot_user_id 查找其所属的 dept_id
|
||||
with pg_pool.getConn() as conn:
|
||||
with conn.cursor() as cursor:
|
||||
cursor.execute("SELECT dept_id FROM iot_users WHERE name = %s", (user_id,))
|
||||
dept_id = cursor.fetchone()
|
||||
dept_id = str(dept_id[0])
|
||||
return dept_id
|
||||
row = cursor.fetchone()
|
||||
if row is None:
|
||||
return None # 或者抛出自定义异常
|
||||
return str(row[0])
|
||||
|
||||
|
||||
def get_device_type_by_iot_user_name(user_id: str) -> str:
|
||||
@@ -969,9 +980,10 @@ def get_device_type_by_iot_user_name(user_id: str) -> str:
|
||||
with pg_pool.getConn() as conn:
|
||||
with conn.cursor() as cursor:
|
||||
cursor.execute("SELECT type FROM iot_users WHERE name = %s", (user_id,))
|
||||
type = cursor.fetchone()
|
||||
type = str(type[0])
|
||||
return type
|
||||
row = cursor.fetchone()
|
||||
if row is None:
|
||||
return None # 或者抛出自定义异常
|
||||
return str(row[0])
|
||||
|
||||
|
||||
from typing import List
|
||||
|
||||
@@ -4,13 +4,17 @@ from uuid import UUID
|
||||
|
||||
from fastapi import WebSocket
|
||||
|
||||
PROJ_IOT_ONLINE_STATE = 0
|
||||
PROJ_SENTINEL_VEHICLE_STATES = 1
|
||||
PROJ_SENTINEL_MONITOR_STATUS = 2
|
||||
|
||||
|
||||
class ConnectionManager:
|
||||
def __init__(self):
|
||||
self.active_connections: List[dict] = [] # 保存 websocket 和用户信息
|
||||
self.lock = asyncio.Lock()
|
||||
|
||||
# proj_id:0:在线状态 1:畜牧车辆进入
|
||||
# proj_id:0:在线状态 1:畜牧车辆进入 2:畜牧监控大屏
|
||||
async def connect(
|
||||
self, websocket: WebSocket, user_id: UUID, dept_id: str, proj_id: int
|
||||
):
|
||||
@@ -24,6 +28,9 @@ class ConnectionManager:
|
||||
"proj_id": proj_id,
|
||||
}
|
||||
)
|
||||
print(
|
||||
"Device" + str(user_id) + " in project " + str(proj_id) + " connected"
|
||||
)
|
||||
|
||||
async def disconnect(self, websocket: WebSocket):
|
||||
async with self.lock:
|
||||
@@ -34,7 +41,7 @@ class ConnectionManager:
|
||||
async def noticeOnlineStatus(self, message: dict):
|
||||
async with self.lock:
|
||||
for conn in self.active_connections:
|
||||
if conn["proj_id"] == 0:
|
||||
if conn["proj_id"] == PROJ_IOT_ONLINE_STATE:
|
||||
await conn["ws"].send_json(message)
|
||||
|
||||
async def noticeSentinel(
|
||||
@@ -46,5 +53,23 @@ class ConnectionManager:
|
||||
async with self.lock:
|
||||
for conn in self.active_connections:
|
||||
if target_departments:
|
||||
if conn["proj_id"] == 1 and conn["dept_id"] in target_departments:
|
||||
if (
|
||||
conn["proj_id"] == PROJ_SENTINEL_VEHICLE_STATES
|
||||
and conn["dept_id"] in target_departments
|
||||
):
|
||||
await conn["ws"].send_json(message)
|
||||
|
||||
async def noticeSentinelMonitorStatus(
|
||||
self, message: dict, target_departments: List[UUID] = None
|
||||
):
|
||||
"""
|
||||
target_departments: 指定哪些部门能收到消息
|
||||
"""
|
||||
async with self.lock:
|
||||
for conn in self.active_connections:
|
||||
if target_departments:
|
||||
if (
|
||||
conn["proj_id"] == PROJ_SENTINEL_MONITOR_STATUS
|
||||
and conn["dept_id"] in target_departments
|
||||
):
|
||||
await conn["ws"].send_json(message)
|
||||
|
||||
Reference in New Issue
Block a user