rescue_units.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. # from fastapi import APIRouter, HTTPException, Depends, Body,Query
  2. from fastapi import APIRouter, Request, Depends, HTTPException, Query, BackgroundTasks
  3. from fastapi.responses import JSONResponse
  4. import os
  5. # from sqlalchemy.orm import Session
  6. from sqlalchemy.orm import Session, joinedload
  7. import xlrd
  8. from database import get_db, get_db_share
  9. from models import *
  10. from typing import List, Optional
  11. from pydantic import BaseModel,Extra, Field
  12. import uuid
  13. from common.security import valid_access_token
  14. from pydantic import BaseModel
  15. from exceptions import AppException, HmacException
  16. from common.security import valid_access_token
  17. import traceback
  18. from utils import *
  19. from common.auth_user import *
  20. from common.db import db_czrz
  21. from sqlalchemy import create_engine, Column, Integer, String, Boolean, MetaData, Table, \
  22. inspect, exists,or_,text,insert,asc,desc
  23. # 目录在文档上传接口写死
  24. UPLOAD_mergefile_PATH = '/data/upload/mergefile'
  25. router = APIRouter()
  26. # 救灾人员单位
  27. # Pydantic 模型
  28. class UnitSchema(BaseModel):
  29. id: int = None
  30. name: str = None
  31. category: str = None
  32. contact_number: str = None
  33. responsible_person: str = None
  34. contact_number: str = None
  35. team_size: int = None
  36. supervisor_unit: str = None
  37. unit_prop: str = None
  38. unit_level: str = None
  39. unit_favor: str = None
  40. supervisor_unit_phone: str = None
  41. supervisor_unit_contact: str = None
  42. responsible_person_phone: str = None
  43. area: str = None
  44. founding_time: str = None
  45. address: str = None
  46. longitude: str = None
  47. latitude: str = None
  48. position: str = None
  49. is_delete: int = 0
  50. class UnitListSchema(BaseModel):
  51. units: List[UnitSchema] = Field(default_factory=list)
  52. class Config:
  53. orm_mode = True
  54. #创建
  55. @router.post("/")
  56. def create_units(unit_list_data: UnitListSchema, db: Session = Depends(get_db)):
  57. units = unit_list_data.units
  58. if not units: # 确保列表不为空
  59. raise HTTPException(status_code=400, detail="单位列表不能为空")
  60. try:
  61. new_units = [] # 创建一个空列表来存储新对象
  62. for unit_data in units:
  63. unit_data = unit_data.dict(exclude_none=True)
  64. unit_data["add_time"] = datetime.now()
  65. print(unit_data)
  66. new_unit = RescueUnit(**unit_data)
  67. db.add(new_unit)
  68. db.commit()
  69. db.refresh(new_unit)
  70. new_units.append(new_unit)
  71. unit_ids = [unit.id for unit in new_units] # 获取所有新对象的ID
  72. return {"code": 200, "msg": "创建成功", "unit_ids": unit_ids}
  73. except Exception as e:
  74. traceback.print_exc()
  75. db.rollback()
  76. raise HTTPException(status_code=400, detail=str(e))
  77. #删除
  78. @router.delete("/{unit_id}")
  79. def delete_unit(unit_id: int, db: Session = Depends(get_db), user_id=Depends(valid_access_token)):
  80. unit = db.query(RescueUnit).get(unit_id)
  81. if not unit:
  82. raise HTTPException(status_code=404, detail="单位不存在")
  83. try:
  84. # 更新 is_delete 字段为 1,而不是删除记录
  85. unit.is_delete = 1
  86. db.commit()
  87. return {"code": 200, "msg": "删除成功"}
  88. except Exception as e:
  89. traceback.print_exc()
  90. db.rollback()
  91. raise HTTPException(status_code=400, detail=str(e))
  92. # class UnitListQueryParams(BaseModel):
  93. # page: int = Field(default=1, gt=0)
  94. # page_size: int = Field(default=10, gt=0)
  95. #查询列表
  96. @router.get("/list")
  97. def get_units(page: int = Query(default=1, gt=0),
  98. pageSize: int = Query(default=10, gt=0),
  99. db: Session = Depends(get_db),
  100. user_id=Depends(valid_access_token)):
  101. # 应用过滤条件,仅查询未被删除的单位
  102. data_query = db.query(RescueUnit).filter(RescueUnit.is_delete == 0)
  103. data_query = data_query.order_by(RescueUnit.add_time.desc())
  104. # 计算总数
  105. total_count = data_query.count()
  106. # 分页查询
  107. offset = (page - 1) * pageSize
  108. units = data_query.offset(offset).limit(pageSize).all()
  109. # 构造结果
  110. result_items = [unit.to_dict() for unit in units]
  111. result = {
  112. "code": 200,
  113. 'msg': '查询成功',
  114. 'total': total_count,
  115. 'totalPages': (total_count + pageSize - 1) // pageSize,
  116. 'page': page,
  117. 'pageSize': pageSize,
  118. 'data': result_items
  119. }
  120. return result
  121. #查询详情
  122. @router.get("/detail/{unit_id}")
  123. def get_unit_by_id(unit_id: int, db: Session = Depends(get_db), user_id=Depends(valid_access_token)):
  124. # unit = db.query(Unit).filter(Unit.is_delete == 0).get(unit_id)
  125. unit = db.query(RescueUnit).filter_by(id=unit_id, is_delete=0).first()
  126. if not unit:
  127. raise HTTPException(status_code=404, detail="单位不存在或已被标记为删除")
  128. return {"code": 200, "msg": "查询成功", "unit": unit.to_dict()}
  129. #修改
  130. @router.put("/edit/{unit_id}")
  131. def update_unit(unit_id: int, update_data: UnitSchema, db: Session = Depends(get_db),
  132. user_id=Depends(valid_access_token)):
  133. # 根据id和is_delete字段获取单位
  134. unit = db.query(RescueUnit).filter_by(id=unit_id, is_delete=0).first()
  135. if not unit:
  136. raise HTTPException(status_code=404, detail="单位不存在或已被标记为删除")
  137. try:
  138. # 更新非空字段,排除id字段
  139. for key, value in update_data.dict(exclude_none=True).items():
  140. # 确保不更新id字段
  141. if key != 'id':
  142. setattr(unit, key, value)
  143. db.commit()
  144. db.refresh(unit)
  145. return {"code": 200, "msg": "更新成功", "unit": unit.to_dict()}
  146. except Exception as e:
  147. traceback.print_exc()
  148. db.rollback()
  149. raise HTTPException(status_code=400, detail=str(e))
  150. # 导入
  151. @router.post('/import')
  152. async def import_doc(
  153. request: Request,
  154. db: Session = Depends(get_db),
  155. body = Depends(remove_xss_json),
  156. user_id = Depends(valid_access_token)
  157. ):
  158. # print(body)
  159. try:
  160. filename = body['filename']
  161. if len(filename) == 0:
  162. raise Exception()
  163. file = filename[0]
  164. url = file['url']
  165. file_path = f"{UPLOAD_mergefile_PATH}/uploads/{url}"
  166. file_path = os.path.abspath(file_path)
  167. print(file_path)
  168. book = xlrd.open_workbook(file_path)
  169. sheet = book.sheet_by_index(0)
  170. data = []
  171. '''
  172. for i in range(9, sheet.nrows):
  173. # 预案名称
  174. plan_name = sheet.cell(i, 0).value
  175. # 一级目录
  176. title1 = sheet.cell(i, 1).value
  177. # 二级目录
  178. title2 = sheet.cell(i, 2).value
  179. # 三级目录
  180. title3 = sheet.cell(i, 3).value
  181. # 正文
  182. content = sheet.cell(i, 4).value
  183. if len(plan_name) < 1 and len(title1) < 1 and len(title2) < 1 and len(title3) < 1 and len(content) < 1 :
  184. break
  185. data.append({
  186. 'plan_name': plan_name,
  187. 'title1': title1,
  188. 'title2': title2,
  189. 'title3': title3,
  190. 'content': content,
  191. })
  192. if len(data) > 0:
  193. db.query(EmergencyDoc).filter(EmergencyDoc.plan_id == plan_id).delete()
  194. db.commit()
  195. title1 = ''
  196. content = ''
  197. docs = []
  198. for n in data:
  199. if n['title1'] != '':
  200. if len(docs) > 0:
  201. add_doc_1(db, title1, content, docs, plan_id)
  202. docs = []
  203. title1 = n['title1']
  204. content = n['content']
  205. if n['title2'] != '':
  206. docs.append(n)
  207. continue
  208. docs.append(n)
  209. if len(docs) > 0:
  210. add_doc_1(db, title1, content, docs, plan_id)
  211. '''
  212. return {
  213. 'code': 200,
  214. 'msg': '导入成功'
  215. }
  216. except Exception:
  217. traceback.print_exc()
  218. return {
  219. 'code': 500,
  220. 'msg': '导入发生异常'
  221. }
  222. @router.get("/export")
  223. async def get_list_info(
  224. request: Request,
  225. keyword: str = Query(None),
  226. auth_user: AuthUser = Depends(find_auth_user),
  227. db: Session = Depends(get_db_share),
  228. mmdb:Session = Depends(get_db)
  229. ):
  230. try:
  231. query = db.query(EmergencyExpertInfo)
  232. if keyword:
  233. query = query.filter(or_(EmergencyExpertInfo.name.like(f'%{keyword}%'),
  234. EmergencyExpertInfo.unit.like(f'%{keyword}%'),
  235. EmergencyExpertInfo.professional_title.like(f'%{keyword}%'),
  236. EmergencyExpertInfo.professional_group.like(f'%{keyword}%'),
  237. EmergencyExpertInfo.professional_field.like(f'%{keyword}%')))
  238. data = query.all()
  239. data = [{'序号':info.id,
  240. '姓名':info.name,
  241. '所属区县':info.county,
  242. '专家类型':info.expert_type,
  243. '荣誉称号':info.honorary_title,
  244. '单位' :info.unit,
  245. '职位' :info.position,
  246. '职称' :info.professional_title,
  247. '擅长事故类型' :info.specialty,
  248. '救援经历' :info.rescue_experience,
  249. '出生日期' :info.birth_date,
  250. '工作时间' :info.work_start_date,
  251. '发证日期' :info.certificate_issue_date,
  252. '专业分组' :info.professional_group,
  253. '专业领域' :info.professional_field,
  254. '工作电话' :info.work_phone,
  255. '住宅电话' :info.home_phone,
  256. '移动电话' :info.mobile_phone,
  257. '电子邮箱' :info.email,
  258. '联系地址' :info.contact_address,
  259. '经度' :info.longitude,
  260. '纬度' :info.latitude} for info in data]
  261. # 返回结果
  262. import pandas as pd
  263. from io import BytesIO
  264. # 将查询结果转换为 DataFrame
  265. df = pd.DataFrame(data)
  266. # 将 DataFrame 导出为 Excel 文件
  267. output = BytesIO()
  268. with pd.ExcelWriter(output, engine='openpyxl') as writer:
  269. df.to_excel(writer, index=False)
  270. # 设置响应头
  271. output.seek(0)
  272. from urllib.parse import quote
  273. encoded_filename = f'应急专家管理导出{datetime.now().strftime("%Y%m%d%H%mi%s")}.xlsx'
  274. encoded_filename = quote(encoded_filename, encoding='utf-8')
  275. headers = {
  276. 'Content-Disposition': f'attachment; filename*=UTF-8\'\'{encoded_filename}',
  277. 'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
  278. }
  279. db_czrz.log(mmdb, auth_user, "应急专家管理", f"应急专家管理导出数据成功", request.client.host)
  280. # 返回文件流
  281. return StreamingResponse(output, headers=headers)
  282. except Exception as e:
  283. traceback.print_exc()
  284. return JSONResponse(status_code=500, content={'msg': f"Internal server error: {str(e)}", 'code': 500})