Initial commit
This commit is contained in:
commit
17a4bc8994
|
@ -0,0 +1,2 @@
|
|||
# 忽略venv文件夹
|
||||
venv/
|
|
@ -0,0 +1,8 @@
|
|||
# 默认忽略的文件
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# 基于编辑器的 HTTP 客户端请求
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
|
@ -0,0 +1 @@
|
|||
health_service_api
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Python 3.11 (health_service_api)" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
|
@ -0,0 +1,54 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="DuplicatedCode" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="NonAsciiCharacters" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="ignoredPackages">
|
||||
<value>
|
||||
<list size="9">
|
||||
<item index="0" class="java.lang.String" itemvalue="pandas" />
|
||||
<item index="1" class="java.lang.String" itemvalue="reportlab" />
|
||||
<item index="2" class="java.lang.String" itemvalue="gevent" />
|
||||
<item index="3" class="java.lang.String" itemvalue="numpy" />
|
||||
<item index="4" class="java.lang.String" itemvalue="Django" />
|
||||
<item index="5" class="java.lang.String" itemvalue="tzdata" />
|
||||
<item index="6" class="java.lang.String" itemvalue="asgiref" />
|
||||
<item index="7" class="java.lang.String" itemvalue="python-multipart" />
|
||||
<item index="8" class="java.lang.String" itemvalue="sqlparse" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PyPep8Inspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
||||
<option name="ignoredErrors">
|
||||
<list>
|
||||
<option value="E501" />
|
||||
<option value="E127" />
|
||||
</list>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PyPep8NamingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
||||
<option name="ignoredErrors">
|
||||
<list>
|
||||
<option value="N806" />
|
||||
</list>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PyProtectedMemberInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="PyUnresolvedReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="ignoredIdentifiers">
|
||||
<list>
|
||||
<option value="str.*" />
|
||||
</list>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
||||
<option name="processCode" value="true" />
|
||||
<option name="processLiterals" value="true" />
|
||||
<option name="processComments" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="SqlDialectInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="SqlNoDataSourceInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
</profile>
|
||||
</component>
|
|
@ -0,0 +1,6 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11 (health_service_api)" project-jdk-type="Python SDK" />
|
||||
</project>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/health_service_api.iml" filepath="$PROJECT_DIR$/.idea/health_service_api.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,433 @@
|
|||
import ast
|
||||
import copy
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
from pathlib import Path
|
||||
from typing import Dict
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, UploadFile, File
|
||||
import openpyxl
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
from interval import Interval
|
||||
from openpyxl.utils import get_column_letter
|
||||
from pyuca import Collator
|
||||
from starlette import status
|
||||
from starlette.responses import FileResponse
|
||||
|
||||
from APP.Schemas import ComputeSchemas
|
||||
from Utils.DataBase.MongoHelperUtils import MongoHelper, get_mongodb
|
||||
|
||||
router = APIRouter(
|
||||
prefix="/api/health_industry"
|
||||
)
|
||||
|
||||
|
||||
def calculate_expression(expression: ast.Expression, params: Dict) -> float:
|
||||
"""
|
||||
使用AST模块计算安全的表达式
|
||||
"""
|
||||
try:
|
||||
code = compile(expression, "<string>", "eval")
|
||||
result = eval(code, {}, params)
|
||||
return result
|
||||
except SyntaxError as e:
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="公式语法错误:" + str(e))
|
||||
except NameError as e:
|
||||
raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="公式中存在未定义的变量:" + str(e))
|
||||
except TypeError as e:
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="公式中的某些操作不支持所提供的参数类型:" + str(e))
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="执行公式时出现错误:" + str(e))
|
||||
|
||||
|
||||
@router.post("/upload_model_excel", summary="上传模型excel", tags=["模型仓库"])
|
||||
async def func(file: UploadFile = File(...), mongodb: MongoHelper = Depends(get_mongodb)):
|
||||
contents = await file.read()
|
||||
data = dict()
|
||||
xls = pd.read_excel(contents, sheet_name=None)
|
||||
for sheet_name, df in xls.items():
|
||||
if sheet_name == '得分级别标准':
|
||||
data['得分级别标准'] = df.set_index('得分级别标准')['Unnamed: 1'].to_dict()
|
||||
elif sheet_name == '档位得分标准':
|
||||
data['档位得分标准'] = df.set_index('档位得分标准')['Unnamed: 1'].to_dict()
|
||||
elif sheet_name == '级别调整':
|
||||
data['级别调整'] = df.set_index('级别调整').index.to_list()
|
||||
else:
|
||||
df = df.replace(np.nan, None)
|
||||
search = mongodb.find_data_by_condition(dbname="打分模型", sheet="模型集",
|
||||
condition={"模型名称": sheet_name})
|
||||
if search:
|
||||
raise HTTPException(status_code=202, detail="模型已存在")
|
||||
data['模型名称'] = sheet_name
|
||||
data_list = []
|
||||
# 补充df指标缺失值
|
||||
df.loc[:, '一级指标'] = df['一级指标'].fillna(method="ffill")
|
||||
df.loc[:, '二级指标'] = df['二级指标'].fillna(method="ffill")
|
||||
df.loc[:, '三级指标'] = df['三级指标'].fillna(method="ffill")
|
||||
df.loc[:, '四级指标'] = df['四级指标'].fillna(method="ffill")
|
||||
for index, row in df.iterrows():
|
||||
data_list.append(row.to_dict())
|
||||
data['指标数据'] = data_list
|
||||
mongodb.insert_data(dbname="打分模型", sheet="模型集", data=data)
|
||||
return {
|
||||
"code": 200,
|
||||
"message": "上传成功"
|
||||
}
|
||||
|
||||
|
||||
@router.post("/download", summary="导出模型填报数据", tags=["模型仓库"])
|
||||
def func(name: str = '模型名称', year: str = "2023", mongodb: MongoHelper = Depends(get_mongodb)):
|
||||
# 根据名称查询模型是否存在
|
||||
search = mongodb.find_data_by_condition(dbname="打分模型", sheet="模型集", condition={"模型名称": name})
|
||||
if not search:
|
||||
raise HTTPException(status_code=202, detail="模型不存在")
|
||||
|
||||
index = search.get('指标数据')
|
||||
|
||||
# 参数集
|
||||
params = list()
|
||||
|
||||
# 清洗所有公式需要的参数值
|
||||
for item in index:
|
||||
formula = item.get('计算公式')
|
||||
if isinstance(formula, str):
|
||||
pattern = re.compile('[\u4e00-\u9fa5]+')
|
||||
matches = pattern.findall(formula)
|
||||
for match in matches:
|
||||
params.append(match)
|
||||
|
||||
params = list(set(params))
|
||||
|
||||
param_dict = dict()
|
||||
for param in params:
|
||||
param_dict[param] = None
|
||||
year_dict = dict()
|
||||
year_dict[year] = param_dict
|
||||
|
||||
excel = os.path.join(os.getcwd(), 'Utils', 'File', 'template', '填报模板.xlsx')
|
||||
|
||||
# 生成财务数据填报excel
|
||||
sheet_01 = pd.DataFrame(year_dict)
|
||||
# 创建ExcelWriter对象
|
||||
writer = pd.ExcelWriter(excel)
|
||||
sheet_01.to_excel(writer, sheet_name='填报数据表')
|
||||
writer.close()
|
||||
|
||||
file_path = Path(excel)
|
||||
wb = openpyxl.load_workbook(file_path)
|
||||
for sheet_name in wb.sheetnames:
|
||||
sheet = wb[sheet_name]
|
||||
for column in range(1, sheet.max_column + 1):
|
||||
letter = get_column_letter(column)
|
||||
max_length = 0
|
||||
for cell in sheet[letter]:
|
||||
try:
|
||||
if len(str(cell.value)) > max_length:
|
||||
max_length = len(str(cell.value))
|
||||
except Exception:
|
||||
pass
|
||||
adjusted_width = (max_length + 18)
|
||||
sheet.column_dimensions[letter].width = adjusted_width
|
||||
wb.save(file_path)
|
||||
return FileResponse(file_path, media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
filename=file_path.name)
|
||||
|
||||
|
||||
@router.post("/upload", summary="上传填报数据excel", tags=["模型仓库"])
|
||||
async def func(file: UploadFile = File(...)):
|
||||
data = dict()
|
||||
contents = await file.read()
|
||||
xls = pd.read_excel(contents, sheet_name=None)
|
||||
for sheet_name, df in xls.items():
|
||||
df = df.set_index('Unnamed: 0')
|
||||
df.columns.name = 'Year'
|
||||
df.columns = df.columns.str.strip()
|
||||
result = dict()
|
||||
for col in df.columns:
|
||||
if df[col].isna().any().any():
|
||||
raise HTTPException(status_code=400, detail="数据未填报完整")
|
||||
result[str(col)] = df[col].to_dict()
|
||||
data[sheet_name] = result
|
||||
return {
|
||||
"code": 200,
|
||||
"message": "上传成功",
|
||||
"content": data
|
||||
}
|
||||
|
||||
|
||||
@router.post("/index_calculate", summary="指标计算", tags=["模型仓库"])
|
||||
def func(schemas: ComputeSchemas.ComputeModelReqBody, mongodb: MongoHelper = Depends(get_mongodb)):
|
||||
search = mongodb.find_data_by_condition(dbname="打分模型", sheet="模型集", condition={"模型名称": schemas.name})
|
||||
if not search:
|
||||
raise HTTPException(status_code=202, detail="模型不存在")
|
||||
|
||||
index = search.get('指标数据')
|
||||
data = schemas.index
|
||||
result = dict()
|
||||
|
||||
# 计算该模型共有几层指标
|
||||
index_list = list()
|
||||
for key in index[0].keys():
|
||||
if '指标' in key:
|
||||
index_list.append(key.replace("级指标", ""))
|
||||
collator = Collator()
|
||||
sorted_words = sorted(index_list, key=collator.sort_key)
|
||||
min_index = sorted_words[-1] + '级指标'
|
||||
|
||||
# 遍历指标,定性指标直接返回None,定量指标进行计算
|
||||
for item in index:
|
||||
name = item.get(min_index)
|
||||
formula = item.get('计算公式')
|
||||
if isinstance(formula, str) and formula != '-':
|
||||
# 获取指标值
|
||||
params = dict()
|
||||
pattern = re.compile('[\u4e00-\u9fa5]+')
|
||||
matches = pattern.findall(formula)
|
||||
for match in matches:
|
||||
params[match] = data.get(match)
|
||||
|
||||
expression_ast = ast.parse(formula, mode="eval")
|
||||
result[name] = str(round(calculate_expression(expression_ast, params), 2))
|
||||
else:
|
||||
result[name] = None
|
||||
|
||||
return {
|
||||
"code": 200,
|
||||
"message": "计算完成",
|
||||
"content": result
|
||||
}
|
||||
|
||||
|
||||
@router.post("/score_calculate", summary="计算得分", tags=["模型仓库"])
|
||||
def func(schemas: ComputeSchemas.ComputeModelReqBody, mongodb: MongoHelper = Depends(get_mongodb)):
|
||||
search = mongodb.find_data_by_condition(dbname="打分模型", sheet="模型集", condition={"模型名称": schemas.name})
|
||||
if not search:
|
||||
raise HTTPException(status_code=202, detail="模型不存在")
|
||||
|
||||
index_data = search.get('指标数据')
|
||||
score_standard = search.get('得分级别标准')
|
||||
gear_positio = search.get('档位得分标准')
|
||||
|
||||
# 计算该模型共有几层指标
|
||||
index_list = list()
|
||||
for key in index_data[0].keys():
|
||||
if '指标' in key:
|
||||
index_list.append(key.replace("级指标", ""))
|
||||
collator = Collator()
|
||||
sorted_words = sorted(index_list, key=collator.sort_key)
|
||||
min_index = sorted_words[-1] + '级指标'
|
||||
|
||||
# 指标数值数据
|
||||
data = schemas.index
|
||||
|
||||
def score_func(lev, wei):
|
||||
num = gear_positio.get(lev)
|
||||
return round(num / 100 * wei, 2)
|
||||
|
||||
index_score = list()
|
||||
for index in index_data:
|
||||
index_dict = copy.deepcopy(index)
|
||||
# 指标名称
|
||||
index_name = index.get(min_index)
|
||||
# 指标数值
|
||||
value = data.get(index_name)
|
||||
index_dict['数值'] = data.get(index_name)
|
||||
# 指标权重
|
||||
weight = index.get('权重')
|
||||
# 指标数值分为四种:常规数值型、直接进在区间内进行计算,部分区间可能缺失;财务指标数值型,经过计算的财务指标数值直接在区间进行计算;字符串型,直接与档位匹配,布尔型:是与否,一档与八档
|
||||
if isinstance(value, str):
|
||||
# 遍历档位
|
||||
for key, val in index.items():
|
||||
if '档' in key and value == val:
|
||||
index_dict['得分'] = score_func(key, weight)
|
||||
index_dict['档位'] = key
|
||||
index_score.append(index_dict)
|
||||
elif isinstance(value, float) or isinstance(value, int):
|
||||
for gear_key, gear_value in index.items():
|
||||
if '档' in gear_key:
|
||||
try:
|
||||
values = gear_value
|
||||
begin = values[0]
|
||||
end = values[-1]
|
||||
number = values[1:-1]
|
||||
|
||||
def judge_type(num):
|
||||
if num == '+inf':
|
||||
num = float('inf')
|
||||
elif num == '-inf':
|
||||
num = float('-inf')
|
||||
else:
|
||||
num = float(num)
|
||||
return num
|
||||
|
||||
begin_numeber = judge_type(number[0:number.rfind(',')])
|
||||
end_numeber = judge_type(number[number.rfind(','):].replace(",", "").strip())
|
||||
|
||||
# 区间各种情况
|
||||
zoom = None
|
||||
if begin == "(" and end == ")":
|
||||
zoom = Interval(begin_numeber, end_numeber, closed=False)
|
||||
elif begin == "(" and end == "]":
|
||||
zoom = Interval(begin_numeber, end_numeber, lower_closed=False)
|
||||
elif begin == "[" and end == "]":
|
||||
zoom = Interval(begin_numeber, end_numeber)
|
||||
elif begin == "[" and end == ")":
|
||||
zoom = Interval(begin_numeber, end_numeber, upper_closed=False)
|
||||
|
||||
if float(value) in zoom:
|
||||
index_dict['得分'] = score_func(gear_key, weight)
|
||||
index_dict['档位'] = gear_key
|
||||
index_score.append(index_dict)
|
||||
break
|
||||
except Exception:
|
||||
index_dict['得分'] = score_func(gear_key, weight)
|
||||
index_dict['档位'] = gear_key
|
||||
index_score.append(index_dict)
|
||||
break
|
||||
|
||||
# 汇总得分
|
||||
score = round(sum(item.get('得分') for item in index_score), 2)
|
||||
rank_level = 'C'
|
||||
for le, s in score_standard.items():
|
||||
if score > s:
|
||||
rank_level = le
|
||||
break
|
||||
|
||||
return {
|
||||
"code": 200,
|
||||
"message": "计算成功",
|
||||
"content": {
|
||||
"level": rank_level,
|
||||
"total_score": score,
|
||||
"indicator": index_score
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@router.post("/batch_score_calculate", summary="批量计算得分(测试用)", tags=["模型仓库"])
|
||||
async def func(name: str = "模型名称", file: UploadFile = File(...), mongodb: MongoHelper = Depends(get_mongodb)):
|
||||
search = mongodb.find_data_by_condition(dbname="打分模型", sheet="模型集", condition={"模型名称": name})
|
||||
if not search:
|
||||
raise HTTPException(status_code=202, detail="模型不存在")
|
||||
|
||||
index_data = search.get('指标数据')
|
||||
score_standard = search.get('得分级别标准')
|
||||
gear_positio = search.get('档位得分标准')
|
||||
|
||||
# 计算该模型共有几层指标
|
||||
index_list = list()
|
||||
for key in index_data[0].keys():
|
||||
if '指标' in key:
|
||||
index_list.append(key.replace("级指标", ""))
|
||||
collator = Collator()
|
||||
sorted_words = sorted(index_list, key=collator.sort_key)
|
||||
min_index = sorted_words[-1] + '级指标'
|
||||
|
||||
# 读取excel文件
|
||||
contents = await file.read()
|
||||
data_list = []
|
||||
xls = pd.read_excel(contents, sheet_name=None)
|
||||
for sheet_name, df in xls.items():
|
||||
if sheet_name == '测试企业':
|
||||
for index, row in df.iterrows():
|
||||
data_list.append(row.to_dict())
|
||||
|
||||
def score_func(lev, wei):
|
||||
num = gear_positio.get(lev)
|
||||
return round(num / 100 * wei, 2)
|
||||
|
||||
def score_level_func(res_score):
|
||||
rank_level = 'C'
|
||||
for le, s in score_standard.items():
|
||||
if res_score > s:
|
||||
rank_level = le
|
||||
break
|
||||
return rank_level
|
||||
|
||||
# 遍历公司数据
|
||||
result_list = list()
|
||||
for item in data_list:
|
||||
result_dict = dict()
|
||||
result_dict['企业名称'] = item.get('公司中文名称')
|
||||
result_dict['证券代码'] = item.get('证券代码')
|
||||
result_dict['证券简称'] = item.get('证券简称')
|
||||
result_dict['分类'] = item.get('分类')
|
||||
# 遍历指标打分
|
||||
index_score = list()
|
||||
for index in index_data:
|
||||
index_dict = copy.deepcopy(index)
|
||||
# 指标名称
|
||||
index_name = index.get(min_index)
|
||||
# 指标数值
|
||||
value = item.get(index_name)
|
||||
index_dict['数值'] = item.get(index_name)
|
||||
# 指标权重
|
||||
weight = index.get('权重')
|
||||
# 指标数值分为四种:常规数值型、直接进在区间内进行计算,部分区间可能缺失;财务指标数值型,经过计算的财务指标数值直接在区间进行计算;字符串型,直接与档位匹配,布尔型:是与否,一档与八档
|
||||
if isinstance(value, str):
|
||||
# 遍历档位
|
||||
for key, val in index.items():
|
||||
if '档' in key and value == val:
|
||||
index_dict['得分'] = score_func(key, weight)
|
||||
index_dict['档位'] = key
|
||||
index_score.append(index_dict)
|
||||
elif isinstance(value, float) or isinstance(value, int):
|
||||
for gear_key, gear_value in index.items():
|
||||
if '档' in gear_key:
|
||||
try:
|
||||
values = gear_value
|
||||
begin = values[0]
|
||||
end = values[-1]
|
||||
number = values[1:-1]
|
||||
|
||||
def judge_type(num):
|
||||
if num == '+inf':
|
||||
num = float('inf')
|
||||
elif num == '-inf':
|
||||
num = float('-inf')
|
||||
else:
|
||||
num = float(num)
|
||||
return num
|
||||
|
||||
begin_numeber = judge_type(number[0:number.rfind(',')])
|
||||
end_numeber = judge_type(number[number.rfind(','):].replace(",", "").strip())
|
||||
|
||||
# 区间各种情况
|
||||
zoom = None
|
||||
if begin == "(" and end == ")":
|
||||
zoom = Interval(begin_numeber, end_numeber, closed=False)
|
||||
elif begin == "(" and end == "]":
|
||||
zoom = Interval(begin_numeber, end_numeber, lower_closed=False)
|
||||
elif begin == "[" and end == "]":
|
||||
zoom = Interval(begin_numeber, end_numeber)
|
||||
elif begin == "[" and end == ")":
|
||||
zoom = Interval(begin_numeber, end_numeber, upper_closed=False)
|
||||
|
||||
if float(value) in zoom:
|
||||
index_dict['得分'] = score_func(gear_key, weight)
|
||||
index_dict['档位'] = gear_key
|
||||
index_score.append(index_dict)
|
||||
break
|
||||
except Exception:
|
||||
index_dict['得分'] = score_func(gear_key, weight)
|
||||
index_dict['档位'] = gear_key
|
||||
index_score.append(index_dict)
|
||||
break
|
||||
|
||||
result_dict['指标'] = index_score
|
||||
score = sum(i.get('得分') for i in index_score)
|
||||
result_dict['总分'] = sum(i.get('权重') for i in index_score)
|
||||
result_dict['得分'] = score
|
||||
result_dict['级别'] = score_level_func(score)
|
||||
print(result_dict)
|
||||
time.sleep(1)
|
||||
result_dict.pop('指标')
|
||||
result_list.append(result_dict)
|
||||
|
||||
df = pd.DataFrame(result_list)
|
||||
df.to_excel('测试数据打分结果.xlsx', index=False)
|
||||
return result_list
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,7 @@
|
|||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class ComputeModelReqBody(BaseModel):
|
||||
name: str = "模型名称"
|
||||
index: dict = {}
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"Mysql": {
|
||||
"wr_report_flow": "mysql+pymysql://root:123456@localhost/wr_report_flow?charset=utf8mb4"
|
||||
},
|
||||
"MongoDB": {
|
||||
"test": "root:123456@116.63.159.166:27017",
|
||||
"local": "localhost:27017"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
import re
|
||||
import os
|
||||
import json
|
||||
|
||||
import gridfs
|
||||
import pymongo
|
||||
|
||||
from urllib import parse
|
||||
from bson import ObjectId
|
||||
|
||||
|
||||
class MongoHelper:
|
||||
|
||||
def __init__(self, param):
|
||||
"""
|
||||
param:
|
||||
type:str
|
||||
desc: 选择连接哪个MongoDB数据库
|
||||
"""
|
||||
with open(os.path.abspath(os.path.dirname(__file__) + '/DBConfig.json')) as f:
|
||||
db_configs = json.load(f)
|
||||
this_mongo_cfg = db_configs['MongoDB'][param]
|
||||
m = re.match(r'([\s\S].*?):([\s\S].*)@([\s\S].*)', this_mongo_cfg)
|
||||
parsed_mongo_config = "{}:{}@{}".format(parse.quote_plus(m.group(1)), parse.quote_plus(m.group(2)), m.group(3))
|
||||
self.client = pymongo.MongoClient('mongodb://{}'.format(parsed_mongo_config))
|
||||
|
||||
def insert_data(self, dbname: str, sheet: str, data: dict):
|
||||
collection = self.client[dbname][sheet]
|
||||
item = collection.insert_one(data)
|
||||
return item.inserted_id.__str__()
|
||||
|
||||
def delete_data_by_id(self, dbname: str, sheet: str, _id: str):
|
||||
collection = self.client[dbname][sheet]
|
||||
collection.delete_one({'_id': ObjectId(_id)})
|
||||
return True
|
||||
|
||||
def find_data_by_id(self, dbname: str, sheet: str, _id: str):
|
||||
collection = self.client[dbname][sheet]
|
||||
return collection.find_one({'_id': ObjectId(_id)}, {"_id": False})
|
||||
|
||||
def find_data_by_name(self, dbname: str, sheet: str, name: str):
|
||||
collection = self.client[dbname][sheet]
|
||||
return collection.find_one({'name': name}, {"_id": False})
|
||||
|
||||
def find_data_by_condition(self, dbname: str, sheet: str, condition: dict):
|
||||
collection = self.client[dbname][sheet]
|
||||
return collection.find_one(condition, {"_id": False})
|
||||
|
||||
def query_data(self, dbname: str, sheet: str, name: str, page: int, pagesize: int):
|
||||
collection = self.client[dbname][sheet]
|
||||
if name:
|
||||
query = {'name': name}
|
||||
else:
|
||||
query = {}
|
||||
total_count = collection.count_documents(query)
|
||||
results = collection.find(query, {"_id": False}).skip((page - 1) * pagesize).limit(pagesize)
|
||||
return list(results), total_count
|
||||
|
||||
def delete_data_by_name(self, dbname: str, sheet: str, name: str):
|
||||
collection = self.client[dbname][sheet]
|
||||
collection.delete_one({'name': name})
|
||||
return True
|
||||
|
||||
def update_data_by_id(self, dbname: str, sheet: str, _id: str, data: dict):
|
||||
collection = self.client[dbname][sheet]
|
||||
collection.update_one({'_id': ObjectId(_id)}, {"$set": data})
|
||||
return True
|
||||
|
||||
def update_data_by_name(self, dbname: str, sheet: str, name: str, data: dict):
|
||||
collection = self.client[dbname][sheet]
|
||||
collection.update_one({'name': name}, {"$set": data})
|
||||
return True
|
||||
|
||||
def insert_file(self, file: bytes):
|
||||
fs = gridfs.GridFS(self.client['评级报告'], 'docx')
|
||||
return fs.put(file)
|
||||
|
||||
def get_file(self, fid: str):
|
||||
fs = gridfs.GridFS(self.client['评级报告'], 'docx')
|
||||
gf = fs.get(ObjectId(fid))
|
||||
return gf.read()
|
||||
|
||||
|
||||
def get_mongodb():
|
||||
try:
|
||||
db = MongoHelper("test")
|
||||
yield db
|
||||
finally:
|
||||
db.client.close()
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,21 @@
|
|||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
|
||||
from APP.Router import HealthIndustryRouter
|
||||
|
||||
app = FastAPI(
|
||||
title="保健服务后端接口",
|
||||
description="保健服务评级打分流程相关",
|
||||
version="v1.0.0"
|
||||
)
|
||||
|
||||
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["*"],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
app.include_router(HealthIndustryRouter.router)
|
|
@ -0,0 +1,10 @@
|
|||
fastapi==0.95.1
|
||||
interval==1.0.0
|
||||
numpy==1.24.2
|
||||
openpyxl==3.1.2
|
||||
pandas==2.0.1
|
||||
pydantic==1.10.7
|
||||
pymongo==4.3.3
|
||||
pyuca==1.2
|
||||
starlette==0.26.1
|
||||
python-multipart==0.0.6
|
Loading…
Reference in New Issue