__init__.py 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689
  1. import json
  2. import random
  3. from sqlalchemy import create_engine, select
  4. from utils.StripTagsHTMLParser import *
  5. from sqlalchemy.orm import Session
  6. from sqlalchemy import text, exists, and_, or_, not_
  7. import traceback
  8. from models import *
  9. from common.db import db_task
  10. from common.security import valid_access_token
  11. from datetime import datetime, timedelta
  12. from fastapi import APIRouter, Depends, HTTPException, Response, Query
  13. from database import get_db
  14. from pydantic import BaseModel
  15. from utils import *
  16. import copy
  17. from config import settings
  18. from common import YzyApi
  19. from common.db import db_event_management, db_user, db_msg_center, db_yzy, db_dept, db_czrz
  20. from common.enc import mpfun
  21. router = APIRouter()
  22. @router.post('/create')
  23. async def create_task(
  24. request: Request,
  25. db: Session = Depends(get_db),
  26. body=Depends(remove_xss_json),
  27. user_id=Depends(valid_access_token)):
  28. try:
  29. # 验证必需的字段
  30. required_fields = ['task_description', 'unit_name', 'registrar','event_code']
  31. missing_fields = [field for field in required_fields if field not in body]
  32. if missing_fields:
  33. raise HTTPException(status_code=401, detail=f"Missing required fields: {', '.join(missing_fields)}")
  34. event_code = db.query(EventBase).filter(EventBase.event_code == body.get('event_code')).first()
  35. if not event_code:
  36. return Response(content="事件不存在", status_code=400)
  37. unit_id = db_dept.get_dept_id_by_name(db, body['unit_name'])
  38. task_id = db_task.get_next_event_id(db)
  39. imgList = []
  40. if 'imgList' in body:
  41. imgList = body['imgList']
  42. del body['imgList']
  43. fileList = []
  44. if 'fileList' in body:
  45. fileList = body['fileList']
  46. del body['fileList']
  47. task_base = TaskRegistration(
  48. **body,
  49. task_id = task_id,
  50. unit_id = unit_id,
  51. registrar_id = user_id
  52. )
  53. db.add(task_base)
  54. db.commit()
  55. db.refresh(task_base)
  56. for file in imgList:
  57. file_name = file['url']
  58. file_name_desc = file['name']
  59. status = file['status']
  60. new_file = TaskFile(
  61. file_id=new_guid(),
  62. foreign_key=task_base.id,
  63. from_scenario='task_img',
  64. file_name=file_name,
  65. file_name_desc=file_name_desc,
  66. status=status
  67. )
  68. db.add(new_file)
  69. db.commit()
  70. for file in fileList:
  71. file_name = file['url']
  72. file_name_desc = file['name']
  73. status = file['status']
  74. new_file = TaskFile(
  75. file_id=new_guid(),
  76. foreign_key=task_base.id,
  77. from_scenario='task_file',
  78. file_name=file_name,
  79. file_name_desc=file_name_desc,
  80. status=status
  81. )
  82. db.add(new_file)
  83. db.commit()
  84. # 发送粤政易消息
  85. send_yzy_msg(db, task_base, user_id)
  86. try:
  87. user_info = db_user.get_user_info(db, user_id)
  88. db_czrz.log_username(db, user_id, mpfun.dec_data(user_info.user_name), user_info.nick_name, "应急一张图", "任务下达", request.client.host)
  89. except:
  90. traceback.print_exc()
  91. return {
  92. "code": 200,
  93. "msg": "任务创建成功",
  94. "data": task_id
  95. }
  96. except Exception as e:
  97. db.rollback()
  98. traceback.print_exc()
  99. raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
  100. # 发送粤政易消息
  101. def send_yzy_msg(db: Session, task_base: TaskRegistration, recorded_by: int) -> None:
  102. to_user_id = task_base.executor_id
  103. user_info = db_user.get_user_info(db, to_user_id)
  104. yzy_account = user_info.yzy_account
  105. yzy_userid = db_yzy.get_userid_by_account(db, yzy_account)
  106. event_title = db_event_management.get_event_title(db, task_base.event_code)
  107. create_time = get_datetime_str(task_base.creation_time)
  108. detail_url = "{}{}".format(settings.YZY_WEB_ROOT, "/yjxp/")
  109. description = "事件名称: " + event_title + "\n发布时间:" + create_time + "\n任务内容: "+task_base.task_description
  110. data = {
  111. "yzy_userid": yzy_userid,
  112. "mobile": yzy_account,
  113. "content": description,
  114. "recorded_by": recorded_by,
  115. "detail_url": detail_url,
  116. "foreign_key": task_base.task_id,
  117. "from_scenario": "task_registrations",
  118. "title": f"{event_title}任务"
  119. }
  120. YzyApi.add_to_msg_queue(db, data)
  121. db_msg_center.add_message(db, "任务消息", to_user_id, f"{event_title}任务", task_base.task_description, task_base.task_id, 'task_registrations')
  122. class TaskQuery(BaseModel):
  123. task_id: str = None
  124. task_description: str = None
  125. unit_name: str = None
  126. registrar: str = None
  127. creation_time: str = None
  128. processing_status: str = None
  129. @router.post('/select')
  130. @router.get('/select')
  131. async def select_tasks(
  132. request: Request,
  133. db: Session = Depends(get_db),
  134. query: TaskQuery = Depends(),
  135. sortBy: str = Query(None, description="排序字段"),
  136. sortOrder: str = Query(None, description="排序顺序"),
  137. user_id=Depends(valid_access_token),
  138. pageNum: int = Query(1, gt=0, description="页码"),
  139. event_code: str = Query(None, description="事件ID"),
  140. pageSize: int = Query(10, gt=0, le=100, description="每页大小")):
  141. try:
  142. missing_event_code = db.query(EventBase).filter(EventBase.event_code == event_code).first()
  143. # print(missing_event_code)
  144. if not missing_event_code:
  145. return {
  146. "code": 500,
  147. "msg": "事件不存在"
  148. }
  149. data_query = db.query(TaskRegistration).filter(TaskRegistration.del_flag != '2')
  150. data_query = data_query.filter(TaskRegistration.event_code == event_code)
  151. # 应用过滤条件
  152. if query.task_id:
  153. data_query = data_query.filter(TaskRegistration.task_id == query.task_id)
  154. if query.task_description:
  155. data_query = data_query.filter(TaskRegistration.task_description == query.task_description)
  156. if query.unit_name:
  157. data_query = data_query.filter(TaskRegistration.unit_name == query.unit_name)
  158. if query.registrar:
  159. data_query = data_query.filter(TaskRegistration.registrar == query.registrar)
  160. if query.creation_time:
  161. data_query = data_query.filter(TaskRegistration.creation_time == query.creation_time)
  162. if query.processing_status:
  163. data_query = data_query.filter(TaskRegistration.processing_status == query.processing_status)
  164. # print(TaskRegistration,sortBy)
  165. if sortBy:
  166. if hasattr(TaskRegistration, sortBy):
  167. print("xx")
  168. sort_attr = getattr(TaskRegistration, sortBy)
  169. data_query = data_query.order_by(sort_attr.asc() if sortOrder == 'asc' else sort_attr.desc())
  170. total_count = data_query.count()
  171. offset = (pageNum - 1) * pageSize
  172. data_query = data_query.offset(offset).limit(pageSize)
  173. rows = data_query.all()
  174. data = []
  175. for row in rows:
  176. info = get_model_dict(row)
  177. info['expire_time'] = get_date_str(info['expire_time'])
  178. info['imgList'] = db_task.get_image_file_list(db, info['task_id'])
  179. info['fileList'] = db_task.get_task_file_list(db, info['task_id'])
  180. info['feebacks'] = db_task.get_task_feebacks(db, info['task_id'])
  181. # # 任务发布后半个小时内没反馈记录就需要alert
  182. info['need_alert'] = db_task.need_task_alert(db, info['task_id'])
  183. data.append(info)
  184. return {
  185. "code": 200,
  186. "msg": "任务查询成功",
  187. "data": data,
  188. "total": total_count,
  189. "pages": (total_count + pageSize - 1) // pageSize,
  190. "current_page": pageNum,
  191. "page_size": pageSize
  192. }
  193. except Exception as e:
  194. db.rollback()
  195. traceback.print_exc()
  196. raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
  197. @router.put('/update')
  198. async def update_task_status(
  199. request: Request,
  200. body = Depends(remove_xss_json),
  201. db: Session = Depends(get_db),
  202. user_id=Depends(valid_access_token)):
  203. try:
  204. task_id_to_use = get_req_param(body, 'task_id')
  205. processing_status = get_req_param(body, 'processing_status')
  206. feedback_content = get_req_param_optional(body, 'feedback_content')
  207. work_station = get_req_param_optional(body, 'work_station')
  208. attachList = None
  209. if 'fileList'in body:
  210. attachList = get_req_param(body, 'fileList')
  211. longitude = latitude = None
  212. if 'lnglat' in body:
  213. longitude = body['lnglat'][0]
  214. latitude = body['lnglat'][1]
  215. if not task_id_to_use:
  216. return Response(content="Missing required parameter 'task_id'", status_code=400)
  217. if processing_status not in ['已完成', '处理中', '待处理','未完成']:
  218. return Response(content="processing_status must be '已完成' or '处理中' or '待处理' or '未完成'", status_code=400)
  219. task_entry = (db.query(TaskRegistration)
  220. .filter(TaskRegistration.del_flag != '2')
  221. .filter(TaskRegistration.task_id == task_id_to_use))
  222. task_entry = task_entry.first()
  223. if not task_entry:
  224. raise HTTPException(status_code=404, detail="任务不存在")
  225. new_feeback = TaskFeeback(
  226. task_id = task_id_to_use,
  227. feeback_user = task_entry.registrar,
  228. content = feedback_content,
  229. processing_status = processing_status,
  230. create_time = datetime.now(),
  231. feeback_type = "0",
  232. leader_unit = "",
  233. leader_name = "",
  234. approval_content = "",
  235. recorded_by=user_id,
  236. longitude = longitude,
  237. latitude = latitude,
  238. work_station = work_station
  239. )
  240. db.add(new_feeback)
  241. db.commit()
  242. task_entry.processing_status = processing_status
  243. task_entry.update_time = datetime.now()
  244. db.commit()
  245. if attachList is not None:
  246. for file in attachList:
  247. file_name = file['url']
  248. file_name_desc = file['name']
  249. status = file['status']
  250. new_file = TaskFile(
  251. file_id=new_guid(),
  252. foreign_key=task_id_to_use,
  253. from_scenario='task_feeback',
  254. file_name=file_name,
  255. file_name_desc=file_name_desc,
  256. status=status
  257. )
  258. db.add(new_file)
  259. db.commit()
  260. return {
  261. "code": 200,
  262. "msg": "任务状态更新成功",
  263. "data": {
  264. "task_id": task_id_to_use,
  265. "processing_status": task_entry.processing_status,
  266. "update_time": task_entry.update_time.isoformat()
  267. }
  268. }
  269. except Exception as e:
  270. traceback.print_exc()
  271. raise HTTPException(status_code=500, detail=str(e))
  272. @router.delete('/delete')
  273. async def delete_task(
  274. request: Request,
  275. db: Session = Depends(get_db),
  276. user_id=Depends(valid_access_token)):
  277. try:
  278. body = await request.json()
  279. task_id_to_use = body.get('taskID')
  280. if not task_id_to_use:
  281. raise HTTPException(status_code=400, detail="Missing required parameter 'taskID'")
  282. event_code = db.query(EventBase).filter(EventBase.event_code == body.get('event_code')).first()
  283. if not event_code:
  284. return Response(content="事件不存在", status_code=400)
  285. task_entry = db.query(TaskRegistration).filter(TaskRegistration.task_id == task_id_to_use).first()
  286. if not task_entry:
  287. raise HTTPException(status_code=404, detail="任务不存在")
  288. task_entry.del_flag = '2'
  289. try:
  290. db.commit()
  291. return {
  292. "code": 200,
  293. "msg": "任务删除成功",
  294. "data": {
  295. "task_id": task_entry.task_id
  296. }
  297. }
  298. except Exception as e:
  299. db.rollback()
  300. raise HTTPException(status_code=500, detail=f"An error occurred while deleting the task: {str(e)}")
  301. except HTTPException as e:
  302. raise e
  303. except Exception as e:
  304. db.rollback()
  305. raise HTTPException(status_code=500, detail=f"An unexpected error occurred: {str(e)}")
  306. @router.get('/selectUnit')
  307. async def select_unit(
  308. request: Request,
  309. db: Session = Depends(get_db),
  310. query: TaskQuery = Depends(),
  311. user_id=Depends(valid_access_token),
  312. ):
  313. try:
  314. # 应该换表,暂时先这样
  315. # update task_unit inner join emergency_contact_info on task_unit.unit_name = emergency_contact_info.unit_name set task_unit.unit_id = emergency_contact_info.unit_id where emergency_contact_info.del_flag = '0' ;
  316. data_query = db.query(TaskUnit).filter(TaskUnit.id != '2').all()
  317. return {
  318. "code": 200,
  319. "msg": "查询成功",
  320. "data": data_query
  321. }
  322. except HTTPException as e:
  323. raise e
  324. except Exception as e:
  325. db.rollback()
  326. raise HTTPException(status_code=500, detail=f"An unexpected error occurred: {str(e)}")
  327. #
  328. # 小屏专用,不敢搞大屏相关代码
  329. #
  330. @router.get('/list')
  331. async def select_tasks(
  332. request: Request,
  333. task_type: str = Query(None),
  334. processing_status: str = Query(None),
  335. search_keyword: str = Query(None),
  336. page: int = Query(1, gt=0, description="页码"),
  337. page_size: int = Query(10, gt=0, le=100, description="每页大小"),
  338. db: Session = Depends(get_db)):
  339. try:
  340. data_query = db.query(TaskRegistration).filter(TaskRegistration.del_flag != '2').filter(TaskRegistration.event_code is not None)
  341. # 应用过滤条件
  342. if task_type is not None:
  343. data_query = data_query.filter(TaskRegistration.task_type == task_type)
  344. if search_keyword is not None:
  345. data_query = data_query.filter(TaskRegistration.task_description.like('%{}%'.format(search_keyword)))
  346. if processing_status is not None:
  347. data_query = data_query.filter(TaskRegistration.processing_status == processing_status)
  348. total_count = data_query.count()
  349. offset = (page - 1) * page_size
  350. data_query = data_query.order_by(TaskRegistration.creation_time.desc()).offset(offset).limit(page_size)
  351. data = []
  352. tasks = data_query.all()
  353. for n in tasks:
  354. task = get_model_dict(n)
  355. if task['processing_status'] == '':
  356. task['processing_status'] = '处理中'
  357. task['creation_time'] = get_datetime_str(task['creation_time'])
  358. task['event_name'] = db_event_management.get_event_title(db, n.event_code)
  359. data.append(task)
  360. return {
  361. "code": 200,
  362. "msg": "任务查询成功",
  363. "data": data,
  364. "total": total_count
  365. }
  366. except Exception as e:
  367. traceback.print_exc()
  368. raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
  369. @router.post("/leader_request")
  370. async def leader_request(
  371. request: Request,
  372. db: Session = Depends(get_db),
  373. body = Depends(remove_xss_json),
  374. user_id = Depends(valid_access_token)
  375. ):
  376. try:
  377. task_id = body['task_id']
  378. processing_status = body['processing_status']
  379. new_feeback = TaskFeeback(
  380. **body,
  381. recorded_by=user_id
  382. )
  383. db.add(new_feeback)
  384. db.commit()
  385. db.query(TaskRegistration).filter(TaskRegistration.task_id == task_id).update(
  386. {
  387. #"processing_status": processing_status,
  388. "update_time": datetime.now()}
  389. )
  390. db.commit()
  391. return {
  392. "code": 200,
  393. "msg": "请示领导保存成功"
  394. }
  395. except Exception as e:
  396. # 处理异常
  397. db.rollback()
  398. traceback.print_exc()
  399. raise HTTPException(status_code=500, detail=str(e))
  400. @router.post("/feeback")
  401. async def feeback(
  402. request: Request,
  403. db: Session = Depends(get_db),
  404. body = Depends(remove_xss_json),
  405. user_id = Depends(valid_access_token)
  406. ):
  407. try:
  408. feeback_user = get_req_param_optional(body, 'feeback_user')
  409. task_id = body['task_id']
  410. processing_status = body['processing_status']
  411. new_file_list = []
  412. if 'fileList' in body:
  413. new_file_list = copy.deepcopy(body['fileList'])
  414. del body['fileList']
  415. if feeback_user == '':
  416. feeback_user = db_user.get_user_info(db, user_id).nick_name
  417. if 'feeback_user' in body:
  418. del body['feeback_user']
  419. new_feeback = TaskFeeback(
  420. **body,
  421. feeback_user=feeback_user,
  422. recorded_by=user_id
  423. )
  424. db.add(new_feeback)
  425. db.commit()
  426. db.refresh(new_feeback)
  427. print(new_file_list)
  428. for file in new_file_list:
  429. file_name = file['file_name']
  430. file_name_desc = file['file_name_desc']
  431. status = file['status']
  432. new_file = TaskFile(
  433. file_id=new_guid(),
  434. foreign_key=new_feeback.id,
  435. from_scenario='task_feeback',
  436. file_name=file_name,
  437. file_name_desc=file_name_desc,
  438. status=status
  439. )
  440. db.add(new_file)
  441. db.commit()
  442. db.query(TaskRegistration).filter(TaskRegistration.task_id == task_id).update({"processing_status": processing_status, "update_time": datetime.now()})
  443. db.commit()
  444. return {
  445. "code": 200,
  446. "msg": "任务反馈保存成功"
  447. }
  448. except Exception as e:
  449. # 处理异常
  450. db.rollback()
  451. traceback.print_exc()
  452. raise HTTPException(status_code=500, detail=str(e))
  453. @router.get('/detail')
  454. async def get_task_detail(
  455. request: Request,
  456. task_id: str = Query(None, description='任务编号'),
  457. db: Session = Depends(get_db)):
  458. print('task_id:',task_id)
  459. try:
  460. # 构建查询
  461. rows = db.query(TaskFeeback).filter(and_(TaskFeeback.task_id == task_id)).all()
  462. feebacks = []
  463. for row in rows:
  464. fileList = []
  465. # 附件
  466. rows = db.query(TaskFile).filter(and_(TaskFile.from_scenario=="task_feeback", TaskFile.foreign_key == row.id, InfoPublishFile.del_flag == '0')).all()
  467. fileList = [
  468. {
  469. "name": row.file_name,
  470. "url": row.storage_file_name
  471. }
  472. for row in rows
  473. ]
  474. info = get_model_dict(row)
  475. info['create_time'] = get_datetime_str(row.create_time)
  476. info['approval_time'] = get_datetime_str(row.approval_time)
  477. info['fileList'] = fileList
  478. info['fileCount'] = len(fileList)
  479. feebacks.append(info)
  480. query = db.query(TaskRegistration)
  481. query = query.filter(TaskRegistration.task_id == task_id)
  482. # 执行查询
  483. row = query.first()
  484. if row is not None:
  485. return {
  486. "code": 200,
  487. "msg": "查询成功",
  488. "data": {
  489. "id": row.id,
  490. "task_id": row.task_id,
  491. "task_type": row.task_type,
  492. "event_code": row.event_code,
  493. "event_name": db_event_management.get_event_title(db, row.event_code),
  494. "processing_status": row.processing_status,
  495. "expire_time": get_datetime_str(row.expire_time),
  496. "update_time": get_datetime_str(row.update_time),
  497. "feeback_user": row.feeback_user,
  498. "task_description": row.task_description,
  499. "feebacks": feebacks
  500. }
  501. }
  502. else:
  503. return {
  504. "code": 500,
  505. "msg": "查询失败"
  506. }
  507. except Exception as e:
  508. # 处理异常
  509. traceback.print_exc()
  510. raise HTTPException(status_code=500, detail=str(e))
  511. # 请示列表
  512. @router.get('/request/list')
  513. async def select_tasks(
  514. request: Request,
  515. task_type: str = Query(None),
  516. processing_status: str = Query(None),
  517. search_keyword: str = Query(None),
  518. page: int = Query(1, gt=0, description="页码"),
  519. page_size: int = Query(10, gt=0, le=100, description="每页大小"),
  520. db: Session = Depends(get_db)):
  521. try:
  522. data_query = db.query(TaskFeeback).filter(TaskFeeback.feeback_type == '1')
  523. # 应用过滤条件
  524. if task_type is not None:
  525. subquery = db.query(TaskRegistration.task_id).filter(and_(TaskRegistration.del_flag == '0', TaskRegistration.task_type == task_type)).subquery()
  526. data_query = data_query.filter(TaskFeeback.task_id == subquery.c.task_id)
  527. if processing_status is not None:
  528. data_query = data_query.filter(TaskFeeback.processing_status == processing_status)
  529. if search_keyword is not None:
  530. data_query = data_query.filter(TaskFeeback.content.like('%{}%'.format(search_keyword)))
  531. total_count = data_query.count()
  532. offset = (page - 1) * page_size
  533. data_query = data_query.order_by(TaskFeeback.create_time.desc()).offset(offset).limit(page_size)
  534. data = []
  535. tasks = data_query.all()
  536. for n in tasks:
  537. task = get_model_dict(n)
  538. task['nick_name'] = db_user.get_nick_name_by_id(db, task['recorded_by'])
  539. task['create_time'] = get_datetime_str(task['create_time'])
  540. task['approval_time'] = get_datetime_str(task['approval_time'])
  541. task['update_time'] = task['create_time']
  542. if task['approval_time'] != None:
  543. task['update_time'] = task['approval_time']
  544. task['event_name'] = ''
  545. task_id = task['task_id']
  546. reg_info = db.query(TaskRegistration).filter(TaskRegistration.task_id == task_id).first()
  547. if reg_info is not None:
  548. reg_info = get_model_dict(reg_info)
  549. task['event_name'] = db_event_management.get_event_title(db, reg_info['event_code'])
  550. data.append(task)
  551. return {
  552. "code": 200,
  553. "msg": "请示查询成功",
  554. "data": data,
  555. "total": total_count
  556. }
  557. except Exception as e:
  558. traceback.print_exc()
  559. raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
  560. # 请示批复
  561. @router.post("/approval")
  562. async def approval(
  563. request: Request,
  564. db: Session = Depends(get_db),
  565. body = Depends(remove_xss_json),
  566. user_id = Depends(valid_access_token)
  567. ):
  568. try:
  569. feeback_id = get_req_param(body, "feeback_id")
  570. approval_content = get_req_param_optional(body, 'approval_content')
  571. row = db.query(TaskFeeback).filter(TaskFeeback.id == feeback_id).first()
  572. if row is None:
  573. return {
  574. "code": 500,
  575. "msg": "请示不存在"
  576. }
  577. row.approval_content = approval_content
  578. row.approval_time = datetime.now()
  579. row.processing_status = '已完成'
  580. db.commit()
  581. return {
  582. "code": 200,
  583. "msg": "请示批复保存成功"
  584. }
  585. except Exception as e:
  586. # 处理异常
  587. db.rollback()
  588. traceback.print_exc()
  589. raise HTTPException(status_code=500, detail=str(e))