267 lines
9.2 KiB
Python
267 lines
9.2 KiB
Python
import ast
|
||
import json
|
||
|
||
import geopandas as gpd
|
||
import pandas as pd
|
||
import psycopg
|
||
from sqlalchemy import create_engine
|
||
|
||
from app.native.api.postgresql_info import get_pgconn_string
|
||
|
||
|
||
# 2025/03/23
|
||
def create_user(name: str, username: str, password: str):
|
||
"""
|
||
创建用户
|
||
:param name: 数据库名称
|
||
:param username: 用户名
|
||
:param password: 密码
|
||
:return:
|
||
"""
|
||
try:
|
||
# 动态替换数据库名称
|
||
conn_string = get_pgconn_string(db_name=name)
|
||
# 连接到 PostgreSQL 数据库(这里是数据库 "bb")
|
||
with psycopg.connect(conn_string) as conn:
|
||
with conn.cursor() as cur:
|
||
cur.execute(
|
||
"INSERT INTO users (username, password) VALUES (%s, %s)",
|
||
(username, password),
|
||
)
|
||
# 提交事务
|
||
conn.commit()
|
||
print("新用户创建成功!")
|
||
except Exception as e:
|
||
print(f"创建用户出错:{e}")
|
||
|
||
|
||
# 2025/03/23
|
||
def delete_user(name: str, username: str):
|
||
"""
|
||
删除用户
|
||
:param name: 数据库名称
|
||
:param username: 用户名
|
||
:return:
|
||
"""
|
||
try:
|
||
# 动态替换数据库名称
|
||
conn_string = get_pgconn_string(db_name=name)
|
||
# 连接到 PostgreSQL 数据库(这里是数据库 "bb")
|
||
with psycopg.connect(conn_string) as conn:
|
||
with conn.cursor() as cur:
|
||
cur.execute("DELETE FROM users WHERE username = %s", (username,))
|
||
conn.commit()
|
||
print(f"用户 {username} 删除成功!")
|
||
except Exception as e:
|
||
print(f"删除用户出错:{e}")
|
||
|
||
|
||
# 2025/03/23
|
||
def scheme_name_exists(name: str, scheme_name: str) -> bool:
|
||
"""
|
||
判断传入的 scheme_name 是否已存在于 scheme_list 表中,用于输入框判断
|
||
:param name: 数据库名称
|
||
:param scheme_name: 需要判断的方案名称
|
||
:return: 如果存在返回 True,否则返回 False
|
||
"""
|
||
try:
|
||
conn_string = get_pgconn_string(db_name=name)
|
||
with psycopg.connect(conn_string) as conn:
|
||
with conn.cursor() as cur:
|
||
cur.execute(
|
||
"SELECT COUNT(*) FROM scheme_list WHERE scheme_name = %s",
|
||
(scheme_name,),
|
||
)
|
||
result = cur.fetchone()
|
||
if result is not None and result[0] > 0:
|
||
return True
|
||
else:
|
||
return False
|
||
except Exception as e:
|
||
print(f"查询 scheme_name 时出错:{e}")
|
||
return False
|
||
|
||
|
||
# 2025/03/23
|
||
def store_scheme_info(
|
||
name: str,
|
||
scheme_name: str,
|
||
scheme_type: str,
|
||
username: str,
|
||
scheme_start_time: str,
|
||
scheme_detail: dict,
|
||
):
|
||
"""
|
||
将一条方案记录插入 scheme_list 表中
|
||
:param name: 数据库名称
|
||
:param scheme_name: 方案名称
|
||
:param scheme_type: 方案类型
|
||
:param username: 用户名(需在 users 表中已存在)
|
||
:param scheme_start_time: 方案起始时间(字符串)
|
||
:param scheme_detail: 方案详情(字典,会转换为 JSON)
|
||
:return:
|
||
"""
|
||
try:
|
||
conn_string = get_pgconn_string(db_name=name)
|
||
with psycopg.connect(conn_string) as conn:
|
||
with conn.cursor() as cur:
|
||
sql = """
|
||
INSERT INTO scheme_list (scheme_name, scheme_type, username, scheme_start_time, scheme_detail)
|
||
VALUES (%s, %s, %s, %s, %s)
|
||
"""
|
||
# 将字典转换为 JSON 字符串
|
||
scheme_detail_json = json.dumps(scheme_detail)
|
||
cur.execute(
|
||
sql,
|
||
(
|
||
scheme_name,
|
||
scheme_type,
|
||
username,
|
||
scheme_start_time,
|
||
scheme_detail_json,
|
||
),
|
||
)
|
||
conn.commit()
|
||
print("方案信息存储成功!")
|
||
except Exception as e:
|
||
print(f"存储方案信息时出错:{e}")
|
||
|
||
|
||
# 2025/03/23
|
||
def delete_scheme_info(name: str, scheme_name: str) -> None:
|
||
"""
|
||
从 scheme_list 表中删除指定的方案
|
||
:param name: 数据库名称
|
||
:param scheme_name: 要删除的方案名称
|
||
"""
|
||
try:
|
||
conn_string = get_pgconn_string(db_name=name)
|
||
with psycopg.connect(conn_string) as conn:
|
||
with conn.cursor() as cur:
|
||
# 使用参数化查询删除方案记录
|
||
cur.execute(
|
||
"DELETE FROM scheme_list WHERE scheme_name = %s", (scheme_name,)
|
||
)
|
||
conn.commit()
|
||
print(f"方案 {scheme_name} 删除成功!")
|
||
except Exception as e:
|
||
print(f"删除方案时出错:{e}")
|
||
|
||
|
||
# 2025/03/23
|
||
def query_scheme_list(name: str) -> list:
|
||
"""
|
||
查询pg数据库中的scheme_list,按照 create_time 降序排列,离现在时间最近的记录排在最前面
|
||
:param name: 项目名称(数据库名称)
|
||
:return: 返回查询结果的所有行
|
||
"""
|
||
try:
|
||
# 动态替换数据库名称
|
||
conn_string = get_pgconn_string(db_name=name)
|
||
# 连接到 PostgreSQL 数据库(这里是数据库 "bb")
|
||
with psycopg.connect(conn_string) as conn:
|
||
with conn.cursor() as cur:
|
||
# 按 create_time 降序排列
|
||
cur.execute("SELECT * FROM scheme_list ORDER BY create_time DESC")
|
||
rows = cur.fetchall()
|
||
return rows
|
||
|
||
except Exception as e:
|
||
print(f"查询错误:{e}")
|
||
|
||
|
||
# 2025/03/23
|
||
def upload_shp_to_pg(name: str, table_name: str, role: str, shp_file_path: str):
|
||
"""
|
||
将 Shapefile 文件上传到 PostgreSQL 数据库
|
||
:param name: 项目名称(数据库名称)
|
||
:param table_name: 创建表的名字
|
||
:param role: 数据库角色名,位于c盘user中查看
|
||
:param shp_file_path: shp文件的路径
|
||
:return:
|
||
"""
|
||
try:
|
||
# 动态连接到指定的数据库
|
||
conn_string = get_pgconn_string(db_name=name)
|
||
with psycopg.connect(conn_string) as conn:
|
||
# 读取 Shapefile 文件
|
||
gdf = gpd.read_file(shp_file_path)
|
||
|
||
# 检查投影坐标系(CRS),并确保是 EPSG:4326
|
||
if gdf.crs.to_string() != "EPSG:4490":
|
||
gdf = gdf.to_crs(epsg=4490)
|
||
|
||
# 使用 GeoDataFrame 的 .to_postgis 方法将数据写入 PostgreSQL
|
||
# 需要在数据库中提前安装 PostGIS 扩展
|
||
engine = create_engine(f"postgresql+psycopg2://{role}:@127.0.0.1/{name}")
|
||
gdf.to_postgis(
|
||
table_name, engine, if_exists="replace", index=True, index_label="id"
|
||
)
|
||
|
||
print(
|
||
f"Shapefile 文件成功上传到 PostgreSQL 数据库 '{name}' 的表 '{table_name}'."
|
||
)
|
||
|
||
except Exception as e:
|
||
print(f"上传 Shapefile 到 PostgreSQL 时出错:{e}")
|
||
|
||
|
||
def submit_risk_probability_result(name: str, result_file_path: str) -> None:
|
||
"""
|
||
将管网风险评估结果导入pg数据库
|
||
:param name: 项目名称(数据库名称)
|
||
:param result_file_path: 结果文件路径
|
||
:return:
|
||
"""
|
||
# 自动检测文件编码
|
||
# with open({result_file_path}, 'rb') as file:
|
||
# raw_data = file.read()
|
||
# detected = chardet.detect(raw_data)
|
||
# file_encoding = detected['encoding']
|
||
# print(f"检测到的文件编码:{file_encoding}")
|
||
|
||
try:
|
||
# 动态替换数据库名称
|
||
conn_string = get_pgconn_string(db_name=name)
|
||
|
||
# 连接到 PostgreSQL 数据库
|
||
with psycopg.connect(conn_string) as conn:
|
||
with conn.cursor() as cur:
|
||
# 检查 scada_info 表是否为空
|
||
cur.execute("SELECT COUNT(*) FROM pipe_risk_probability;")
|
||
count = cur.fetchone()[0]
|
||
|
||
if count > 0:
|
||
print("pipe_risk_probability表中已有数据,正在清空记录...")
|
||
cur.execute("DELETE FROM pipe_risk_probability;")
|
||
print("表记录已清空。")
|
||
|
||
# 读取Excel并转换x/y列为列表
|
||
df = pd.read_excel(result_file_path, sheet_name="Sheet1")
|
||
df["x"] = df["x"].apply(ast.literal_eval)
|
||
df["y"] = df["y"].apply(ast.literal_eval)
|
||
|
||
# 批量插入数据
|
||
for index, row in df.iterrows():
|
||
insert_query = """
|
||
INSERT INTO pipe_risk_probability
|
||
(pipeID, pipeage, risk_probability_now, x, y)
|
||
VALUES (%s, %s, %s, %s, %s)
|
||
"""
|
||
cur.execute(
|
||
insert_query,
|
||
(
|
||
row["pipeID"],
|
||
row["pipeage"],
|
||
row["risk_probability_now"],
|
||
row["x"], # 直接传递列表
|
||
row["y"], # 同上
|
||
),
|
||
)
|
||
|
||
conn.commit()
|
||
print("风险评估结果导入成功")
|
||
|
||
except Exception as e:
|
||
print(f"导入时出错:{e}")
|