back.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. from fastapi import APIRouter, Request, Depends, HTTPException, Query
  4. from sqlalchemy.exc import IntegrityError
  5. from fastapi.responses import HTMLResponse, FileResponse
  6. from fastapi.responses import JSONResponse
  7. from database import get_db
  8. from sqlalchemy import text, exists, and_, or_, not_
  9. from sqlalchemy.orm import Session
  10. from models import *
  11. import json
  12. import os
  13. from sqlalchemy import create_engine, select
  14. from typing import Optional
  15. from utils.StripTagsHTMLParser import *
  16. from common.db import db_event_management, db_user, db_area, db_emergency_plan
  17. from common.security import valid_access_token
  18. import traceback
  19. from utils import *
  20. from datetime import datetime, timedelta
  21. from common import YzyApi
  22. from common.db import db_dict
  23. from urllib.parse import quote
  24. import base64
  25. from config import settings
  26. router = APIRouter()
  27. EXAMINE_TYPE_DICT = {
  28. 0: "草稿",
  29. 10: "提交",
  30. 20: "领导审批",
  31. 30: "重新提交"
  32. }
  33. EXAMINE_SUB_TYPE_DICT = {
  34. 0: "草稿",
  35. 10: "提交",
  36. 20: "待审批",
  37. 21: "审批通过",
  38. 22: "审批不通过",
  39. 30: "重新提交"
  40. }
  41. # 信息发布创建
  42. @router.post('/create')
  43. async def create_emergency_plan(
  44. db: Session = Depends(get_db),
  45. body = Depends(remove_xss_json),
  46. user_id = Depends(valid_access_token)
  47. ):
  48. try:
  49. dept_id = 0
  50. dept_name = ''
  51. user_row = db.query(SysUser).filter(SysUser.user_id == user_id).first()
  52. user_name = user_row.user_name
  53. nick_name = user_row.nick_name
  54. dept_id = user_row.dept_id
  55. dept_row = db.query(SysDept).filter(SysDept.dept_id == dept_id).first()
  56. dept_name = dept_row.dept_name
  57. examine_user_row = db.query(SysUser).filter(SysUser.user_name == body['examine_user']).first()
  58. if examine_user_row is None:
  59. return {
  60. "code": 500,
  61. "msg": "审批人员账号不存在"
  62. }
  63. examine_by = examine_user_row.user_id
  64. new_publish = InfoPublishBase(
  65. title = body['title'],
  66. publish_group = body['publish_group'],
  67. template_id = body['template_id'],
  68. content = body['content'],
  69. recorded_by = user_id,
  70. del_flag = '0',
  71. dept_id = dept_id,
  72. dept_name = dept_name,
  73. add_time = datetime.now(),
  74. response_type = body['response_type'],
  75. publish_time = body['publish_time'],
  76. examine_by = examine_by,
  77. publish_status = 0,
  78. examine_status = 0,
  79. publish_channel = body['publish_channel'],
  80. user_count = body['user_count'],
  81. user_ok_count = 0,
  82. user_err_count = 0,
  83. user_sending_count = 0,
  84. info_type = body['info_type']
  85. )
  86. db.add(new_publish)
  87. db.commit()
  88. db.refresh(new_publish)
  89. new_publish_id = new_publish.id
  90. # 发送人员
  91. for u in body['users']:
  92. send_user_id = u['user_id']
  93. send_nick_name = u['nick_name']
  94. send_user_name = ''
  95. send_dept_name = ''
  96. send_yzy_account = ''
  97. user_row = db.query(SysUser).filter(SysUser.user_id == send_user_id).first()
  98. if user_row is not None:
  99. send_user_name = user_row.user_name
  100. send_dept_row = db.query(SysDept).filter(SysDept.dept_id == user_row.dept_id).first()
  101. send_dept_name = send_dept_row.dept_name
  102. send_yzy_account = user_row.yzy_account
  103. if send_yzy_account is None or send_yzy_account == "":
  104. send_yzy_account = user_row.phonenumber
  105. new_resp = InfoPublishResponses(
  106. publish_id = new_publish_id,
  107. user_id = send_user_id,
  108. user_name = send_user_name,
  109. nick_name = send_nick_name,
  110. dept_name = send_dept_name,
  111. sent_status = 0,
  112. yzy_account = send_yzy_account,
  113. response_type = body['response_type'],
  114. publish_channel = body['publish_channel']
  115. )
  116. db.add(new_resp)
  117. db.commit()
  118. # 附件
  119. if 'attachs' in body:
  120. infopublish_files = [
  121. InfoPublishFile(
  122. file_name=fileName["name"],
  123. storage_file_name=fileName["url"],
  124. file_path=f'/data/upload/mergefile/uploads/{fileName["url"]}',
  125. file_size=os.path.getsize(f'/data/upload/mergefile/uploads/{fileName["url"]}'),
  126. foreign_key=str(new_publish_id),
  127. from_scenario="infopublish_attach_file",
  128. update_time=datetime.now(),
  129. create_time=datetime.now(),
  130. create_by=user_id,
  131. create_dept=dept_id,
  132. del_flag='0',
  133. status=0,
  134. )
  135. for fileName in body['attachs']
  136. ]
  137. db.add_all(infopublish_files)
  138. db.commit()
  139. # 审批附件
  140. if 'examine_attachs' in body:
  141. infopublish_files = [
  142. InfoPublishFile(
  143. file_name=fileName["name"],
  144. storage_file_name=fileName["url"],
  145. file_path=f'/data/upload/mergefile/uploads/{fileName["url"]}',
  146. file_size=os.path.getsize(f'/data/upload/mergefile/uploads/{fileName["url"]}'),
  147. foreign_key=str(new_publish_id),
  148. from_scenario="infopublish_examine_attach_file",
  149. update_time=datetime.now(),
  150. create_time=datetime.now(),
  151. create_by=user_id,
  152. create_dept=dept_id,
  153. del_flag='0',
  154. status=0,
  155. )
  156. for fileName in body['examine_attachs']
  157. ]
  158. db.add_all(infopublish_files)
  159. db.commit()
  160. # 审批记录
  161. infopublish_examine = InfoPublishExamine(
  162. publish_id = new_publish_id,
  163. examine_type = 10, # 提交
  164. examine_sub_type = 10, # 提交
  165. examine_time = datetime.now(),
  166. content = '',
  167. user_id = user_id,
  168. user_name = user_name,
  169. nick_name = nick_name,
  170. del_flag = '0'
  171. )
  172. db.add(infopublish_examine)
  173. db.commit()
  174. # 改草稿、待审批状态
  175. db.query(InfoPublishBase).filter(InfoPublishBase.id == new_publish_id).update({"publish_status": 1, "examine_status": 1})
  176. db.commit()
  177. return {
  178. "code": 200,
  179. "msg": "信息创建成功",
  180. "data": new_publish_id
  181. }
  182. except Exception as e:
  183. traceback.print_exc()
  184. # 处理异常
  185. raise HTTPException(status_code=500, detail=str(e))
  186. # 信息发布分页查询
  187. @router.get('/list')
  188. async def get_publish_list(
  189. publish_group: str = Query('', description='发布单位'),
  190. publish_status: str = Query('', description='发布状态的字典键值'),
  191. examine_status: str = Query('', description='审批状态的字典键值'),
  192. dispose_status: str = Query('', description='处理状态的字典键值'),
  193. content: str = Query('', description='信息内容'),
  194. sort_by: str = Query('', description='排序字段'),
  195. sort_order: str = Query("asc", description='排序方式'),
  196. page: int = Query(1, gt=0, description='页码'),
  197. page_size: int = Query(10, gt=0, description='pageSize'),
  198. db: Session = Depends(get_db),
  199. user_id = Depends(valid_access_token)
  200. ):
  201. try:
  202. # 应用查询条件
  203. where = and_(InfoPublishBase.del_flag == '0')
  204. if content != '':
  205. where = and_(where, InfoPublishBase.content.like('%{}%'.format(content)))
  206. if publish_status not in ['', '0'] :
  207. where = and_(where, InfoPublishBase.publish_status == publish_status)
  208. if examine_status not in ['', '0'] :
  209. where = and_(where, InfoPublishBase.examine_status == examine_status)
  210. if publish_group != '':
  211. where = and_(where, InfoPublishBase.publish_group.like('%{}%'.format(publish_group)))
  212. if dispose_status not in ['', '0'] :
  213. where = and_(where, InfoPublishBase.examine_status == 1, InfoPublishBase.examine_by == user_id)
  214. print(where)
  215. # 计算总条目数
  216. q = db.query(func.count(InfoPublishBase.id))
  217. q = q.filter(where)
  218. total = q.scalar()
  219. # 执行分页查询
  220. q = db.query(InfoPublishBase)
  221. q = q.filter(where)
  222. rows = q.order_by(InfoPublishBase.id.desc()).offset((page - 1) * page_size).limit(page_size).all()
  223. data = []
  224. for row in rows:
  225. # 发布申请人
  226. recorded_by = row.recorded_by
  227. user_row = db.query(SysUser).filter(SysUser.user_id == recorded_by).first()
  228. nick_name = ""
  229. dept_name = ""
  230. if user_row is not None:
  231. nick_name = user_row.nick_name
  232. dept_id = user_row.dept_id
  233. dept_row = db.query(SysDept).filter(SysDept.dept_id == dept_id).first()
  234. if dept_row is not None:
  235. dept_name = dept_row.dept_name
  236. # 待处理人
  237. examine_user = "无"
  238. examine_by = row.examine_by
  239. user_row = db.query(SysUser).filter(SysUser.user_id == examine_by).first()
  240. if user_row is not None:
  241. examine_user = user_row.nick_name
  242. data.append({
  243. "id": row.id,
  244. "title": row.title,
  245. "info_type": row.info_type,
  246. "publish_group": row.publish_group,
  247. "content": row.content,
  248. "publish_time": get_datetime_str(row.publish_time),
  249. "publish_channel": row.publish_channel,
  250. "nick_name": nick_name,
  251. "dept_name": dept_name,
  252. "examine_user": examine_user,
  253. "publish_status": row.publish_status, # db_dict.get_dict_label(db, "mm_publish_status", row.publish_status),
  254. "examine_status": row.examine_status, # db_dict.get_dict_label(db, "mm_examine_status", row.examine_status),
  255. "user_count": row.user_count,
  256. "user_ok_count": row.user_ok_count,
  257. "user_err_count": row.user_err_count,
  258. "user_sending_count": row.user_sending_count,
  259. "is_my_edit": (row.examine_status == 0 or row.examine_status == 9) and row.recorded_by == user_id, # 是否我的编辑事项
  260. "is_my_examine": row.examine_status == 1 and int(row.examine_by) == user_id # 是否我的审批事项
  261. })
  262. # 返回结果
  263. return {
  264. "code": 200,
  265. "msg": "查询成功",
  266. "data": data,
  267. "total": total
  268. }
  269. except Exception as e:
  270. # 处理异常
  271. traceback.print_exc()
  272. raise HTTPException(status_code=500, detail=str(e))
  273. # 信息发布查看
  274. @router.get('/edit')
  275. async def get_edit_info(
  276. request: Request,
  277. info_id: str = Query(None, description='信息ID'),
  278. db: Session = Depends(get_db)):
  279. row = db.query(InfoPublishBase).filter(InfoPublishBase.id == info_id).first()
  280. data = get_model_dict(row)
  281. data['examine_user'] = db_user.get_user_name_by_id(db, data['examine_by'])
  282. data['add_time'] = get_datetime_str(data['add_time'])
  283. data['publish_time'] = get_datetime_str(data['publish_time'])
  284. # 反馈 && 未反馈
  285. data['feedback_count'] = db.query(InfoPublishResponses).filter(and_(InfoPublishResponses.publish_id == info_id, InfoPublishResponses.sent_status > 0, InfoPublishResponses.response_type > 0)).count()
  286. data['unresponsive_count'] = db.query(InfoPublishResponses).filter(and_(InfoPublishResponses.publish_id == info_id, InfoPublishResponses.sent_status > 0, InfoPublishResponses.response_type > 0)).count()
  287. # 附件
  288. rows = db.query(InfoPublishFile).filter(and_(InfoPublishFile.from_scenario=="infopublish_attach_file", InfoPublishFile.foreign_key == info_id, InfoPublishFile.del_flag == '0')).all()
  289. data['attachs'] = [
  290. {
  291. "name": row.file_name,
  292. "url": row.storage_file_name
  293. }
  294. for row in rows
  295. ]
  296. # 审批附件
  297. rows = db.query(InfoPublishFile).filter(and_(InfoPublishFile.from_scenario=="infopublish_examine_attach_file", InfoPublishFile.foreign_key == info_id, InfoPublishFile.del_flag == '0')).all()
  298. data['examine_attachs'] = [
  299. {
  300. "name": row.file_name,
  301. "url": row.storage_file_name
  302. }
  303. for row in rows
  304. ]
  305. data["examines"] = []
  306. rows = db.query(InfoPublishExamine).filter(InfoPublishExamine.publish_id == info_id).filter(InfoPublishExamine.del_flag == '0').all()
  307. for row in rows:
  308. data["examines"].append({
  309. "examine_type": EXAMINE_TYPE_DICT[row.examine_type],
  310. "examine_sub_type": EXAMINE_SUB_TYPE_DICT[row.examine_sub_type],
  311. "content": row.content,
  312. "examine_time": get_datetime_str(row.examine_time),
  313. "user_id": row.user_id,
  314. "user_name": row.user_name,
  315. "nick_name": row.nick_name
  316. })
  317. return {
  318. "code": 200,
  319. "msg": "查询成功",
  320. "data": data
  321. }
  322. # 信息发布编辑保存
  323. @router.post('/edit')
  324. async def post_edit_info(
  325. request: Request,
  326. body = Depends(remove_xss_json),
  327. db: Session = Depends(get_db),
  328. user_id = Depends(valid_access_token)):
  329. try:
  330. id = body['id']
  331. remove_req_param(body, 'info_id')
  332. examines = body['examines']
  333. remove_req_param(body, 'examines')
  334. body['recorded_by'] = user_id
  335. db.query(InfoPublishBase).filter(InfoPublishBase.id == id).update(body)
  336. db.commit()
  337. return {
  338. "code": 200,
  339. "msg": "保存信息成功"
  340. }
  341. except Exception as e:
  342. # 处理异常
  343. traceback.print_exc()
  344. raise HTTPException(status_code=500, detail=str(e))
  345. # 信息发布提交审核
  346. @router.post('/examine')
  347. async def post_examine_info(
  348. request: Request,
  349. body = Depends(remove_xss_json),
  350. db: Session = Depends(get_db),
  351. user_id = Depends(valid_access_token)):
  352. user_row = db.query(SysUser).filter(SysUser.user_id == user_id).first()
  353. new_examine = InfoPublishExamine(
  354. pubish_id = body['info_id'],
  355. examine_type = body['examine_type'],
  356. examine_sub_type = body['examine_sub_type'],
  357. content = body['content'],
  358. examine_time = datetime.now(),
  359. user_id = user_id,
  360. user_name = user_row.user_name,
  361. nick_name = user_row.nick_name
  362. )
  363. db.add(new_examine)
  364. db.commit()
  365. return {
  366. "code": 200,
  367. "msg": "保存审批记录成功"
  368. }
  369. # 信息发布查看发送列表
  370. @router.get("/sent_list")
  371. async def get_sent_list(
  372. info_id: str = Query('', description='信息ID'),
  373. channel: str = Query('', description='渠道'),
  374. keywords: str = Query('', description='关键字'),
  375. sort_by: str = Query('', description='排序字段'),
  376. sort_order: str = Query("asc", description='排序方式'),
  377. page: int = Query(1, gt=0, description='页码'),
  378. page_size: int = Query(10, gt=0, description='pageSize'),
  379. db: Session = Depends(get_db)
  380. ):
  381. try:
  382. # 应用查询条件
  383. where = and_(InfoPublishResponses.publish_id == info_id)
  384. if channel != '':
  385. where = and_(where, InfoPublishResponses.publish_channel.like('%{}%'.format(channel)))
  386. # 计算总条目数
  387. q = db.query(func.count(InfoPublishResponses.id))
  388. q = q.filter(where)
  389. total = q.scalar()
  390. # 执行分页查询
  391. q = db.query(InfoPublishResponses)
  392. q = q.filter(where)
  393. rows = q.order_by(InfoPublishResponses.id.desc()).offset((page - 1) * page_size).limit(page_size).all()
  394. data = [
  395. {
  396. "user_id": row.user_id,
  397. "user_name": row.user_name,
  398. "nick_name": row.nick_name,
  399. "dept_name": row.dept_name,
  400. "sent_status": row.sent_status,
  401. "sent_time": get_datetime_str(row.sent_time),
  402. "response_type": get_response_type_text(row.response_type),
  403. "publish_channel": row.publish_channel,
  404. "yzy_account": row.yzy_account,
  405. "yuezhengyiFeedbackStatus": get_sent_status_text(row.sent_status),
  406. "haixinetFeedbackStatus": get_sent_status_text(0),
  407. }
  408. for row in rows
  409. ]
  410. # 返回结果
  411. return {
  412. "code": 200,
  413. "msg": "查询成功",
  414. "data": data,
  415. "total": total
  416. }
  417. except Exception as e:
  418. # 处理异常
  419. traceback.print_exc()
  420. raise HTTPException(status_code=500, detail=str(e))
  421. # 列出可用模板
  422. @router.post("/template_list")
  423. def template_list(db: Session = Depends(get_db)):
  424. try:
  425. rows = db.query(InfoPublishTemplate).filter(InfoPublishTemplate.del_flag == '0').all()
  426. data = [
  427. {
  428. "id": row.id,
  429. "name": row.name,
  430. "content": row.content
  431. }
  432. for row in rows
  433. ]
  434. return {
  435. "code": 200,
  436. "msg": "查询成功",
  437. "data": data,
  438. "total": len(data)
  439. }
  440. except Exception as e:
  441. # 处理异常
  442. traceback.print_exc()
  443. raise HTTPException(status_code=500, detail=str(e))
  444. # 提交审批
  445. @router.post("/submit_examine")
  446. async def submit_examine(
  447. db: Session = Depends(get_db),
  448. body = Depends(remove_xss_json),
  449. user_id = Depends(valid_access_token)
  450. ):
  451. try:
  452. user_row = db.query(SysUser).filter(SysUser.user_id == user_id).first()
  453. info_id = body['info_id']
  454. examine_type = body['examine_type']
  455. content = body['content']
  456. # 审批通过
  457. if examine_type == 'approved':
  458. new_examine = InfoPublishExamine(
  459. publish_id = info_id,
  460. examine_type = 20,
  461. examine_sub_type = 21,
  462. content = content,
  463. examine_time = datetime.now(),
  464. user_id = user_id,
  465. user_name = user_row.user_name,
  466. nick_name = user_row.nick_name
  467. )
  468. db.add(new_examine)
  469. db.commit()
  470. db.query(InfoPublishBase).filter(InfoPublishBase.id == info_id).update({"publish_status": 3, "examine_status": 2})
  471. db.commit()
  472. # 审批不通过
  473. elif examine_type == 'rejected':
  474. new_examine = InfoPublishExamine(
  475. publish_id = info_id,
  476. examine_type = 20,
  477. examine_sub_type = 22,
  478. content = content,
  479. examine_time = datetime.now(),
  480. user_id = user_id,
  481. user_name = user_row.user_name,
  482. nick_name = user_row.nick_name
  483. )
  484. db.add(new_examine)
  485. db.commit()
  486. db.query(InfoPublishBase).filter(InfoPublishBase.id == info_id).update({"publish_status": 0, "examine_status": 0})
  487. db.commit()
  488. return {
  489. "code": 200,
  490. "msg": "审批成功"
  491. }
  492. except Exception as e:
  493. # 处理异常
  494. traceback.print_exc()
  495. raise HTTPException(status_code=500, detail=str(e))
  496. def get_sent_status_text(val: int) -> str:
  497. if val == 0:
  498. return "待发送"
  499. elif val == 1:
  500. return '成功'
  501. elif val == 2:
  502. return '失败'
  503. else:
  504. return "未知"
  505. def get_response_type_text(val: int) -> str:
  506. if val == 0:
  507. return "仅需阅读"
  508. elif val == 1:
  509. return '点击确认'
  510. elif val == 2:
  511. return '签字确认'
  512. else:
  513. return '未知'