__init__.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. from fastapi import APIRouter, Request, Depends, Query, HTTPException, status,WebSocket,WebSocketDisconnect
  4. from common.security import valid_access_token,valid_websocket_token
  5. from fastapi.responses import JSONResponse,StreamingResponse
  6. from common.db import db_czrz
  7. from sqlalchemy.orm import Session
  8. from sqlalchemy.sql import func
  9. from common.auth_user import *
  10. from sqlalchemy import text
  11. from pydantic import BaseModel
  12. from common.BigDataCenterAPI import *
  13. from database import get_db
  14. from typing import List
  15. from models import *
  16. from utils import *
  17. from utils.spatial import *
  18. from utils.ry_system_util import *
  19. from utils.resource_provision_util import *
  20. from common.barcode import create_bar,create_qr
  21. import json
  22. import traceback
  23. import xlrd
  24. import os
  25. # 目录在文档上传接口写死
  26. UPLOAD_mergefile_PATH = '/data/upload/mergefile'
  27. router = APIRouter()
  28. def resource_material_id_get_material_info(db,id,resource_type):
  29. query = db.query(TransportCommunicationMaterial)
  30. query = query.filter_by(id = id,del_flag = '0',resource_type=resource_type)
  31. return query.first()
  32. @router.post("/{resource_type}/create")
  33. async def create_pattern(
  34. resource_type:str,
  35. user_id=Depends(valid_access_token),
  36. body = Depends(remove_xss_json),
  37. db: Session = Depends(get_db)
  38. ):
  39. try:
  40. if resource_type=='comm':
  41. resource_type = 'COMM'
  42. elif resource_type=='transport':
  43. resource_type = 'TRANSPORT'
  44. else:
  45. return JSONResponse(status_code=404,content={'code':404,"msg":"Router not found"})
  46. new_material = TransportCommunicationMaterial(
  47. # id = new_guid(),
  48. code=body['code'],
  49. tool_name=body['tool_name'],
  50. unit=body['unit'],
  51. transport_mode=body['transport_mode'],
  52. material_name=body['material_name'],
  53. material_type=body['material_type'],
  54. admin_div=body['admin_div'],
  55. address=body['address'],
  56. district=body['district'],
  57. longitude=body['longitude'],
  58. latitude=body['latitude'],
  59. person_in_charge=body['person_in_charge'],
  60. contact=body['contact'],
  61. remark=body['remark'],
  62. resource_type=resource_type,
  63. create_by = user_id
  64. )
  65. db.add(new_material)
  66. db.commit()
  67. return {"code": 200, "msg": "创建成功", "data": None}
  68. except Exception as e:
  69. traceback.print_exc()
  70. raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
  71. @router.put("/{resource_type}/update/{id}")
  72. async def update_pattern(
  73. resource_type:str,
  74. id :str ,
  75. user_id=Depends(valid_access_token),
  76. body=Depends(remove_xss_json),
  77. db: Session = Depends(get_db)
  78. ):
  79. try:
  80. if resource_type=='comm':
  81. resource_type = 'COMM'
  82. elif resource_type=='transport':
  83. resource_type = 'TRANSPORT'
  84. else:
  85. return JSONResponse(status_code=404,content={'code':404,"msg":"Router not found"})
  86. info = resource_material_id_get_material_info(db,id,resource_type)
  87. if not info:
  88. return JSONResponse(status_code=404,content={"code":404,"msg":"resource not found"})
  89. # info.room_name = body['room_name']
  90. info.code = body['code']
  91. info.tool_name = body['tool_name']
  92. info.unit = body['unit']
  93. info.transport_mode = body['transport_mode']
  94. info.material_name = body['material_name']
  95. info.material_type = body['material_type']
  96. info.admin_div = body['admin_div']
  97. info.address = body['address']
  98. info.district = body['district']
  99. info.longitude = body['longitude']
  100. info.latitude = body['latitude']
  101. info.person_in_charge = body['person_in_charge']
  102. info.contact = body['contact']
  103. info.remark = body['remark']
  104. info.update_by = user_id
  105. db.commit()
  106. return {"code": 200, "msg": "更新成功"}
  107. except Exception as e:
  108. traceback.print_exc()
  109. raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
  110. @router.get("/{resource_type}/info/{id}")
  111. async def get_pattern_info(
  112. resource_type:str,
  113. id: str,
  114. user_id=Depends(valid_access_token),
  115. db: Session = Depends(get_db)
  116. ):
  117. try:
  118. if resource_type=='comm':
  119. resource_type = 'COMM'
  120. elif resource_type=='transport':
  121. resource_type = 'TRANSPORT'
  122. else:
  123. return JSONResponse(status_code=404,content={'code':404,"msg":"Router not found"})
  124. info = resource_material_id_get_material_info(db,id,resource_type)
  125. if not info:
  126. return JSONResponse(status_code=404,content={"code":404,"msg":"warehouse room not found"})
  127. info = get_model_dict(info)
  128. return {"code": 200, "msg": "获取成功", "data": info}
  129. except Exception as e:
  130. traceback.print_exc()
  131. raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
  132. @router.get("/{resource_type}/list")
  133. async def get_pattern_list(
  134. resource_type:str,
  135. user_id=Depends(valid_access_token),
  136. code: str = Query(None, description='名称'),
  137. tool_name: str = Query(None, description='名称'),
  138. unit: str = Query(None, description='名称'),
  139. transport_mode: str = Query(None, description='名称'),
  140. page: int = Query(1, gt=0, description='页码'),
  141. pageSize: int = Query(10, gt=0, description='每页条目数量'),
  142. db: Session = Depends(get_db)
  143. ):
  144. try:
  145. query = db.query(TransportCommunicationMaterial)
  146. query = query.filter_by(del_flag='0',resource_type=resource_type)
  147. if code:
  148. query = query.filter(TransportCommunicationMaterial.code.like(f'%{code}%'))
  149. if tool_name:
  150. query = query.filter(TransportCommunicationMaterial.tool_name.like(f'%{tool_name}%'))
  151. if unit:
  152. query = query.filter(TransportCommunicationMaterial.unit.like(f'%{unit}%'))
  153. if transport_mode:
  154. query = query.filter(TransportCommunicationMaterial.transport_mode.like(f'%{transport_mode}%'))
  155. total_items = query.count()
  156. # 排序
  157. query = query.order_by(TransportCommunicationMaterial.create_time.desc())
  158. # 执行分页查询
  159. lists = query.offset((page - 1) * pageSize).limit(pageSize).all()
  160. data = []
  161. for info in lists:
  162. data.append(get_model_dict(info))
  163. return {"code": 200, "msg": "查询成功", "data": data,
  164. "total": total_items,
  165. "page": page,
  166. "pageSize": pageSize,
  167. "totalPages": (total_items + pageSize - 1) // pageSize
  168. }
  169. except Exception as e:
  170. traceback.print_exc()
  171. raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
  172. @router.delete("/{resource_type}/delete/{id}")
  173. async def delete_pattern(
  174. resource_type:str,
  175. id :str ,
  176. user_id=Depends(valid_access_token),
  177. body=Depends(remove_xss_json),
  178. db: Session = Depends(get_db)
  179. ):
  180. try:
  181. if resource_type=='comm':
  182. resource_type = 'COMM'
  183. elif resource_type=='transport':
  184. resource_type = 'TRANSPORT'
  185. else:
  186. return JSONResponse(status_code=404,content={'code':404,"msg":"Router not found"})
  187. info = resource_material_id_get_material_info(db,id,resource_type)
  188. if not info:
  189. return JSONResponse(status_code=404,content={"code":404,"msg":"resource not found"})
  190. # info.room_name = body['room_name']
  191. info.del_flag = '2'
  192. info.update_by = user_id
  193. db.commit()
  194. return {"code": 200, "msg": "删除成功"}
  195. except Exception as e:
  196. traceback.print_exc()
  197. raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
  198. import pandas as pd
  199. @router.post("/{resource_type}/import_data")
  200. async def import_data(
  201. resource_type:str,
  202. body = Depends(remove_xss_json),
  203. user_id=Depends(valid_access_token),
  204. db: Session = Depends(get_db)):
  205. if resource_type == 'comm':
  206. resource_type = 'COMM'
  207. elif resource_type == 'transport':
  208. resource_type = 'TRANSPORT'
  209. else:
  210. return JSONResponse(status_code=404, content={'code': 404, "msg": "Router not found"})
  211. # 获取表结构
  212. import os,openpyxl
  213. schema_name = "mmyjhd"
  214. table_name = "transport_communication_material"
  215. columns = [{"column_name":"code","column_comment":"编号"},
  216. {"column_name":"tool_name","column_comment":"运输工具名称"},
  217. {"column_name":"unit","column_comment":"所属单位"},
  218. {"column_name":"transport_mode","column_comment":"运输方式"},
  219. {"column_name":"material_name","column_comment":"物资名称"},
  220. {"column_name":"material_type","column_comment":"物资类型"},
  221. {"column_name":"admin_div","column_comment":"行政区划"},
  222. {"column_name":"address","column_comment":"地址"},
  223. {"column_name":"district","column_comment":"区县"},
  224. {"column_name":"longitude","column_comment":"经度"},
  225. {"column_name":"latitude","column_comment":"纬度"},
  226. {"column_name":"person_in_charge","column_comment":"负责人"},
  227. {"column_name":"contact","column_comment":"联系方式"},
  228. {"column_name":"remark","column_comment":"备注"}]
  229. filename = body['filename']
  230. if '../' in filename or '/' in filename:
  231. return JSONResponse(status_code=400, content={'code': 400, "msg": '警告:禁止篡改文件路径'})
  232. file_path = f'/data/upload/mergefile/uploads/{filename}'
  233. if not os.path.exists(file_path):
  234. return JSONResponse(status_code=404, content={'code': 404, 'msg': f"文件不存在"})
  235. # print("文件不存在,请检查路径!")
  236. # 读取 Excel 文件
  237. try:
  238. workbook = openpyxl.load_workbook(file_path)
  239. sheet = workbook.active
  240. data = pd.read_excel(file_path, header=1).fillna('')
  241. data = data.to_dict(orient='records')
  242. except Exception as e:
  243. traceback.print_exc()
  244. return JSONResponse(status_code=400, content={'code': 400, 'msg': f"接口发生错误:{e}"})
  245. # raise HTTPException(status_code=400, detail="Invalid Excel file")
  246. # 获取字段名和字段备注名
  247. column_names = [col["column_name"] for col in columns if col["column_name"]!='id']
  248. column_comments = [col["column_comment"] for col in columns if col["column_name"]!='id']
  249. # 检查第一行是否为字段备注名
  250. first_row = [cell.value for cell in sheet[1]]
  251. if first_row != column_comments:
  252. print("接口发生错误:Excel columns do not match the expected columns")
  253. return JSONResponse(status_code=400, content={'code': 400, 'msg': f"接口发生错误:Excel columns do not match the expected columns"})
  254. # raise HTTPException(status_code=400, detail="Excel columns do not match the expected columns")
  255. # 检查第二行是否为字段名
  256. second_row = [cell.value for cell in sheet[2]]
  257. if second_row != column_names:
  258. print("接口发生错误:Excel columns do not match the expected columns")
  259. return JSONResponse(status_code=400,
  260. content={'code': 400, 'msg': f"接口发生错误:Excel columns do not match the expected columns"})
  261. # raise HTTPException(status_code=400, detail="Excel columns do not match the expected columns")
  262. # 将数据插入到数据库
  263. try:
  264. new_material_list = []
  265. for row in data:
  266. new_material = TransportCommunicationMaterial(
  267. code=row['code'],
  268. tool_name=row['tool_name'],
  269. unit=row['unit'],
  270. transport_mode=row['transport_mode'],
  271. material_name=row['material_name'],
  272. material_type=row['material_type'],
  273. admin_div=row['admin_div'],
  274. address=row['address'],
  275. district=row['district'],
  276. longitude=row['longitude'],
  277. latitude=row['latitude'],
  278. person_in_charge=row['person_in_charge'],
  279. contact=row['contact'],
  280. remark=row['remark'],
  281. resource_type=resource_type,
  282. create_by=user_id
  283. )
  284. new_material_list.append(new_material)
  285. db.add_all(new_material_list)
  286. db.commit()
  287. # db.execute(insert_query, dict(zip(column_names, row)))
  288. # db.commit()
  289. return {"code":200,"msg": "Data imported successfully"}
  290. except Exception as e:
  291. db.rollback()
  292. traceback.print_exc()
  293. return JSONResponse(status_code=500,
  294. content={'code': 500, 'msg': f"接口发生错误:{e}"})
  295. @router.get("/{resource_type}/export")
  296. async def download_file(
  297. resource_type:str,
  298. code: str = Query(None, description='名称'),
  299. tool_name: str = Query(None, description='名称'),
  300. unit: str = Query(None, description='名称'),
  301. transport_mode: str = Query(None, description='名称'),
  302. db: Session = Depends(get_db),
  303. body = Depends(remove_xss_json),
  304. user_id = Depends(valid_access_token)):
  305. """
  306. 根据提供的文件名下载文件。
  307. :param filename: 要下载的文件的名称。
  308. """
  309. try:
  310. if resource_type == 'comm':
  311. resource_type = 'COMM'
  312. file_name='通讯资源'
  313. elif resource_type == 'transport':
  314. resource_type = 'TRANSPORT'
  315. file_name='运输物资'
  316. else:
  317. return JSONResponse(status_code=404, content={'code': 404, "msg": "Router not found"})
  318. query = db.query(TransportCommunicationMaterial)
  319. query = query.filter_by(del_flag='0', resource_type=resource_type)
  320. if code:
  321. query = query.filter(TransportCommunicationMaterial.code.like(f'%{code}%'))
  322. if tool_name:
  323. query = query.filter(TransportCommunicationMaterial.tool_name.like(f'%{tool_name}%'))
  324. if unit:
  325. query = query.filter(TransportCommunicationMaterial.unit.like(f'%{unit}%'))
  326. if transport_mode:
  327. query = query.filter(TransportCommunicationMaterial.transport_mode.like(f'%{transport_mode}%'))
  328. # 排序
  329. query = query.order_by(TransportCommunicationMaterial.create_time.desc())
  330. # 执行分页查询
  331. lists = query.all()
  332. data_list = []
  333. for info in lists:
  334. data_list.append({"编号": info.code,
  335. "运输工具名称": info.tool_name,
  336. "所属单位": info.unit,
  337. "运输方式": info.transport_mode,
  338. "物资名称": info.material_name,
  339. "物资类型": info.material_type,
  340. "行政区划": info.admin_div,
  341. "地址": info.address,
  342. "区县": info.district,
  343. "经度": info.longitude,
  344. "纬度": info.latitude,
  345. "负责人": info.person_in_charge,
  346. "联系方式": info.contact,
  347. "备注": info.remark})
  348. # 构造文件的完整路径
  349. import pandas as pd
  350. from io import BytesIO
  351. # 将查询结果转换为 DataFrame
  352. df = pd.DataFrame(data_list)
  353. # 将 DataFrame 导出为 Excel 文件
  354. output = BytesIO()
  355. with pd.ExcelWriter(output, engine='openpyxl') as writer:
  356. df.to_excel(writer, index=False)
  357. # 设置响应头
  358. output.seek(0)
  359. from urllib.parse import quote
  360. encoded_filename = f'{file_name}{datetime.now().strftime("%Y%m%d%H%mi%s")}.xlsx'
  361. encoded_filename = quote(encoded_filename, encoding='utf-8')
  362. headers = {
  363. 'Content-Disposition': f'attachment; filename*=UTF-8\'\'{encoded_filename}',
  364. 'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
  365. }
  366. # 返回文件流
  367. return StreamingResponse(output, headers=headers)
  368. except HTTPException as e:
  369. raise e
  370. except Exception as e:
  371. # 处理其他异常情况
  372. traceback.print_exc()
  373. raise HTTPException(status_code=500, detail=str(e))