__init__.py 23 KB

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