back.py 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. from fastapi import APIRouter, Request, Depends, HTTPException, Query
  4. from fastapi.responses import HTMLResponse, FileResponse
  5. from fastapi.responses import JSONResponse
  6. from database import get_db
  7. from sqlalchemy import text, exists, and_, or_, not_
  8. from sqlalchemy.orm import Session
  9. from models import *
  10. import json
  11. import os
  12. from sqlalchemy import create_engine, select
  13. from typing import Optional
  14. from utils.StripTagsHTMLParser import *
  15. from common.db import db_event_management, db_user, db_area, db_emergency_plan
  16. from common.security import valid_access_token
  17. import traceback
  18. from utils import *
  19. from datetime import datetime, timedelta
  20. from common import YzyApi
  21. from common.db import db_dict
  22. from urllib.parse import quote
  23. import base64
  24. from config import settings
  25. from common.enc import mpfun
  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 == mpfun.enc_data(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 = mpfun.dec_data(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 = mpfun.dec_data(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 = mpfun.dec_data(user_name),
  169. nick_name = nick_name,
  170. del_flag = '0'
  171. )
  172. db.add(infopublish_examine)
  173. db.commit()
  174. # 待审批状态
  175. infopublish_examine = InfoPublishExamine(
  176. publish_id = new_publish_id,
  177. examine_type = 20, # 审批
  178. examine_sub_type = 20, # 待审批
  179. examine_time = datetime.now() + timedelta(seconds=1),
  180. content = '',
  181. user_id = examine_by,
  182. user_name = mpfun.dec_data(examine_user_row.user_name),
  183. nick_name = examine_user_row.nick_name,
  184. del_flag = '0'
  185. )
  186. db.add(infopublish_examine)
  187. db.commit()
  188. # 改审核中、待审批状态
  189. db.query(InfoPublishBase).filter(InfoPublishBase.id == new_publish_id).update({"publish_status": 2, "examine_status": 1})
  190. db.commit()
  191. return {
  192. "code": 200,
  193. "msg": "信息创建成功",
  194. "data": new_publish_id
  195. }
  196. except Exception as e:
  197. traceback.print_exc()
  198. # 处理异常
  199. raise HTTPException(status_code=500, detail=str(e))
  200. # 信息发布分页查询
  201. @router.get('/list')
  202. async def get_publish_list(
  203. publish_group: str = Query('', description='发布单位'),
  204. publish_status: str = Query('', description='发布状态的字典键值'),
  205. examine_status: str = Query('', description='审批状态的字典键值'),
  206. dispose_status: str = Query('', description='处理状态的字典键值'),
  207. content: str = Query('', description='信息内容'),
  208. sort_by: str = Query('', description='排序字段'),
  209. sort_order: str = Query("asc", description='排序方式'),
  210. page: int = Query(1, gt=0, description='页码'),
  211. page_size: int = Query(10, gt=0, description='pageSize'),
  212. db: Session = Depends(get_db),
  213. user_id = Depends(valid_access_token)
  214. ):
  215. try:
  216. # 应用查询条件
  217. where = and_(InfoPublishBase.del_flag == '0')
  218. if content != '':
  219. where = and_(where, InfoPublishBase.content.like('%{}%'.format(content)))
  220. if publish_status not in ['', '0'] :
  221. where = and_(where, InfoPublishBase.publish_status == publish_status)
  222. if examine_status not in ['', '0'] :
  223. where = and_(where, InfoPublishBase.examine_status == examine_status)
  224. if publish_group != '':
  225. where = and_(where, InfoPublishBase.publish_group.like('%{}%'.format(publish_group)))
  226. if dispose_status == '1' : # 1 待处理
  227. # 审核类型 20 待审批
  228. subquery = db.query(InfoPublishExamine.publish_id).filter(InfoPublishExamine.del_flag == "0").filter(InfoPublishExamine.user_id == user_id).filter(InfoPublishExamine.examine_sub_type == 20).subquery()
  229. where = and_(where, InfoPublishBase.id == subquery.c.publish_id)
  230. if dispose_status == '2' : # 2 已处理
  231. # 审核类型 21 审批通过 22 审批不通过
  232. subquery = db.query(InfoPublishExamine.publish_id).filter(InfoPublishExamine.del_flag == "0").filter(InfoPublishExamine.user_id == user_id).filter(InfoPublishExamine.examine_sub_type.in_([21,22])).subquery()
  233. where = and_(where, InfoPublishBase.id == subquery.c.publish_id)
  234. # 计算总条目数
  235. q = db.query(func.count(InfoPublishBase.id))
  236. q = q.filter(where)
  237. total = q.scalar()
  238. # 执行分页查询
  239. q = db.query(InfoPublishBase)
  240. q = q.filter(where)
  241. rows = q.order_by(InfoPublishBase.id.desc()).offset((page - 1) * page_size).limit(page_size).all()
  242. data = []
  243. for row in rows:
  244. # 发布申请人
  245. recorded_by = row.recorded_by
  246. user_row = db.query(SysUser).filter(SysUser.user_id == recorded_by).first()
  247. nick_name = ""
  248. dept_name = ""
  249. if user_row is not None:
  250. nick_name = user_row.nick_name
  251. dept_id = user_row.dept_id
  252. dept_row = db.query(SysDept).filter(SysDept.dept_id == dept_id).first()
  253. if dept_row is not None:
  254. dept_name = dept_row.dept_name
  255. # 待处理人
  256. examine_user = "无"
  257. examine_by = row.examine_by
  258. user_row = db.query(SysUser).filter(SysUser.user_id == examine_by).first()
  259. if user_row is not None:
  260. examine_user = user_row.nick_name
  261. # 是否我的审批事项(待审批)
  262. is_my_examine = 0
  263. examine_row = db.query(InfoPublishExamine).filter(InfoPublishExamine.del_flag == "0").filter(InfoPublishExamine.user_id == user_id).filter(InfoPublishExamine.examine_sub_type == 20).order_by(InfoPublishExamine.id.desc()).limit(1).first()
  264. if examine_row is not None:
  265. is_my_examine = 1
  266. data.append({
  267. "id": row.id,
  268. "title": row.title,
  269. "info_type": row.info_type,
  270. "publish_group": row.publish_group,
  271. "content": row.content,
  272. "publish_time": get_datetime_str(row.publish_time),
  273. "publish_channel": row.publish_channel,
  274. "nick_name": nick_name,
  275. "dept_name": dept_name,
  276. "examine_user": examine_user,
  277. "publish_status": row.publish_status, # db_dict.get_dict_label(db, "mm_publish_status", row.publish_status),
  278. "examine_status": row.examine_status, # db_dict.get_dict_label(db, "mm_examine_status", row.examine_status),
  279. "user_count": row.user_count,
  280. "user_ok_count": row.user_ok_count,
  281. "user_err_count": row.user_err_count,
  282. "user_sending_count": row.user_sending_count,
  283. "is_my_edit": (row.examine_status == 0 or row.examine_status == 9) and row.recorded_by == user_id, # 是否我的编辑事项
  284. "is_my_examine": is_my_examine
  285. })
  286. # 返回结果
  287. return {
  288. "code": 200,
  289. "msg": "查询成功",
  290. "data": data,
  291. "total": total
  292. }
  293. except Exception as e:
  294. # 处理异常
  295. traceback.print_exc()
  296. raise HTTPException(status_code=500, detail=str(e))
  297. # 信息发布查看
  298. @router.get('/edit')
  299. async def get_edit_info(
  300. request: Request,
  301. info_id: str = Query(None, description='信息ID'),
  302. db: Session = Depends(get_db)):
  303. row = db.query(InfoPublishBase).filter(InfoPublishBase.id == info_id).first()
  304. data = get_model_dict(row)
  305. examine_time = add_time = data['add_time']
  306. data['examine_user'] = db_user.get_user_name_by_id(db, data['examine_by'])
  307. data['add_time'] = get_datetime_str(data['add_time'])
  308. data['publish_time'] = get_datetime_str(data['publish_time'])
  309. # 反馈 && 未反馈
  310. data['feedback_count'] = db.query(InfoPublishResponses).filter(and_(InfoPublishResponses.publish_id == info_id, InfoPublishResponses.sent_status > 0, InfoPublishResponses.response_type > 0)).count()
  311. data['unresponsive_count'] = db.query(InfoPublishResponses).filter(and_(InfoPublishResponses.publish_id == info_id, InfoPublishResponses.sent_status > 0, InfoPublishResponses.response_type > 0)).count()
  312. # 附件
  313. rows = db.query(InfoPublishFile).filter(and_(InfoPublishFile.from_scenario=="infopublish_attach_file", InfoPublishFile.foreign_key == info_id, InfoPublishFile.del_flag == '0')).all()
  314. data['attachs'] = [
  315. {
  316. "name": row.file_name,
  317. "url": row.storage_file_name
  318. }
  319. for row in rows
  320. ]
  321. # 审批附件
  322. rows = db.query(InfoPublishFile).filter(and_(InfoPublishFile.from_scenario=="infopublish_examine_attach_file", InfoPublishFile.foreign_key == info_id, InfoPublishFile.del_flag == '0')).all()
  323. data['examine_attachs'] = [
  324. {
  325. "name": row.file_name,
  326. "url": row.storage_file_name
  327. }
  328. for row in rows
  329. ]
  330. data["examines"] = []
  331. rows = db.query(InfoPublishExamine).filter(InfoPublishExamine.publish_id == info_id).filter(InfoPublishExamine.del_flag == '0').all()
  332. for row in rows:
  333. examine_time = row.examine_time
  334. data["examines"].append({
  335. "examine_type": EXAMINE_TYPE_DICT[row.examine_type],
  336. "examine_sub_type": EXAMINE_SUB_TYPE_DICT[row.examine_sub_type],
  337. "content": row.content,
  338. "examine_time": get_datetime_str(row.examine_time),
  339. "user_id": row.user_id,
  340. "user_name": row.user_name,
  341. "nick_name": row.nick_name
  342. })
  343. time_diff = examine_time - add_time
  344. data['process_time'] = get_process_time(time_diff)
  345. return {
  346. "code": 200,
  347. "msg": "查询成功",
  348. "data": data
  349. }
  350. # 信息发布编辑保存
  351. @router.post('/edit')
  352. async def post_edit_info(
  353. request: Request,
  354. body = Depends(remove_xss_json),
  355. db: Session = Depends(get_db),
  356. user_id = Depends(valid_access_token)):
  357. try:
  358. id = body['id']
  359. remove_req_param(body, 'info_id')
  360. examines = body['examines']
  361. remove_req_param(body, 'examines')
  362. body['recorded_by'] = user_id
  363. db.query(InfoPublishBase).filter(InfoPublishBase.id == id).update(body)
  364. db.commit()
  365. return {
  366. "code": 200,
  367. "msg": "保存信息成功"
  368. }
  369. except Exception as e:
  370. # 处理异常
  371. traceback.print_exc()
  372. raise HTTPException(status_code=500, detail=str(e))
  373. # 信息发布提交审核
  374. @router.post('/examine')
  375. async def post_examine_info(
  376. request: Request,
  377. body = Depends(remove_xss_json),
  378. db: Session = Depends(get_db),
  379. user_id = Depends(valid_access_token)):
  380. user_row = db.query(SysUser).filter(SysUser.user_id == user_id).first()
  381. new_examine = InfoPublishExamine(
  382. publish_id = body['info_id'],
  383. examine_type = body['examine_type'],
  384. examine_sub_type = body['examine_sub_type'],
  385. content = body['content'],
  386. examine_time = datetime.now(),
  387. user_id = user_id,
  388. user_name = mpfun.dec_data(user_row.user_name),
  389. nick_name = user_row.nick_name
  390. )
  391. db.add(new_examine)
  392. db.commit()
  393. return {
  394. "code": 200,
  395. "msg": "保存审批记录成功"
  396. }
  397. # 信息发布查看发送列表
  398. @router.get("/sent_list")
  399. async def get_sent_list(
  400. info_id: str = Query('', description='信息ID'),
  401. channel: str = Query('', description='渠道'),
  402. keywords: str = Query('', description='关键字'),
  403. sort_by: str = Query('', description='排序字段'),
  404. sort_order: str = Query("asc", description='排序方式'),
  405. page: int = Query(1, gt=0, description='页码'),
  406. page_size: int = Query(10, gt=0, description='pageSize'),
  407. db: Session = Depends(get_db)
  408. ):
  409. try:
  410. # 应用查询条件
  411. where = and_(InfoPublishResponses.publish_id == info_id)
  412. if channel != '':
  413. where = and_(where, InfoPublishResponses.publish_channel.like('%{}%'.format(channel)))
  414. # 计算总条目数
  415. q = db.query(func.count(InfoPublishResponses.id))
  416. q = q.filter(where)
  417. total = q.scalar()
  418. # 执行分页查询
  419. q = db.query(InfoPublishResponses)
  420. q = q.filter(where)
  421. rows = q.order_by(InfoPublishResponses.id.desc()).offset((page - 1) * page_size).limit(page_size).all()
  422. data = [
  423. {
  424. "user_id": row.user_id,
  425. "user_name": row.user_name,
  426. "nick_name": row.nick_name,
  427. "dept_name": row.dept_name,
  428. "sent_status": row.sent_status,
  429. "sent_time": get_datetime_str(row.sent_time),
  430. "response_type": get_response_type_text(row.response_type),
  431. "publish_channel": row.publish_channel,
  432. "yzy_account": row.yzy_account,
  433. "yuezhengyiFeedbackStatus": get_sent_status_text(row.sent_status),
  434. "haixinetFeedbackStatus": get_sent_status_text(0),
  435. }
  436. for row in rows
  437. ]
  438. # 返回结果
  439. return {
  440. "code": 200,
  441. "msg": "查询成功",
  442. "data": data,
  443. "total": total
  444. }
  445. except Exception as e:
  446. # 处理异常
  447. traceback.print_exc()
  448. raise HTTPException(status_code=500, detail=str(e))
  449. # 列出可用模板
  450. @router.post("/template_list")
  451. def template_list(db: Session = Depends(get_db)):
  452. try:
  453. rows = db.query(InfoPublishTemplate).filter(InfoPublishTemplate.del_flag == '0').all()
  454. data = [
  455. {
  456. "id": row.id,
  457. "name": row.name,
  458. "content": row.content
  459. }
  460. for row in rows
  461. ]
  462. return {
  463. "code": 200,
  464. "msg": "查询成功",
  465. "data": data,
  466. "total": len(data)
  467. }
  468. except Exception as e:
  469. # 处理异常
  470. traceback.print_exc()
  471. raise HTTPException(status_code=500, detail=str(e))
  472. # 提交审批
  473. @router.post("/submit_examine")
  474. async def submit_examine(
  475. db: Session = Depends(get_db),
  476. body = Depends(remove_xss_json),
  477. user_id = Depends(valid_access_token)
  478. ):
  479. try:
  480. # 删除之前的待审批记录
  481. db.query(InfoPublishExamine).filter(and_(InfoPublishExamine.examine_type == 20, InfoPublishExamine.examine_sub_type == 20)).update({"del_flag": "2", "content": "content"})
  482. db.commit()
  483. user_row = db.query(SysUser).filter(SysUser.user_id == user_id).first()
  484. info_id = body['info_id']
  485. examine_type = body['examine_type']
  486. content = body['content']
  487. # 审批通过
  488. if examine_type == 'approved':
  489. new_examine = InfoPublishExamine(
  490. publish_id = info_id,
  491. examine_type = 20,
  492. examine_sub_type = 21,
  493. content = content,
  494. examine_time = datetime.now(),
  495. user_id = user_id,
  496. user_name = mpfun.dec_data(user_row.user_name),
  497. nick_name = user_row.nick_name
  498. )
  499. db.add(new_examine)
  500. db.commit()
  501. # publish_status 发布中
  502. # examine_status 审批通过
  503. db.query(InfoPublishBase).filter(InfoPublishBase.id == info_id).update({"publish_status": 3, "examine_status": 3})
  504. db.commit()
  505. # 审批不通过
  506. elif examine_type == 'rejected':
  507. new_examine = InfoPublishExamine(
  508. publish_id = info_id,
  509. examine_type = 20,
  510. examine_sub_type = 22,
  511. content = content,
  512. examine_time = datetime.now(),
  513. user_id = user_id,
  514. user_name = mpfun.dec_data(user_row.user_name),
  515. nick_name = user_row.nick_name
  516. )
  517. db.add(new_examine)
  518. db.commit()
  519. # publish_status 取消发布
  520. # examine_status 审批不通过
  521. db.query(InfoPublishBase).filter(InfoPublishBase.id == info_id).update({"publish_status": 9, "examine_status": 9})
  522. db.commit()
  523. return {
  524. "code": 200,
  525. "msg": "审批成功"
  526. }
  527. except Exception as e:
  528. # 处理异常
  529. traceback.print_exc()
  530. raise HTTPException(status_code=500, detail=str(e))
  531. def get_sent_status_text(val: int) -> str:
  532. if val == 0:
  533. return "待发送"
  534. elif val == 1:
  535. return '成功'
  536. elif val == 2:
  537. return '失败'
  538. else:
  539. return "未知"
  540. def get_response_type_text(val: int) -> str:
  541. if val == 0:
  542. return "仅需阅读"
  543. elif val == 1:
  544. return '点击确认'
  545. elif val == 2:
  546. return '签字确认'
  547. else:
  548. return '未知'