me.py 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  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 io import BytesIO
  26. from PIL import Image
  27. from config import settings
  28. router = APIRouter()
  29. EXAMINE_TYPE_DICT = {
  30. 0: "草稿",
  31. 10: "提交",
  32. 20: "领导审批",
  33. 30: "重新提交"
  34. }
  35. EXAMINE_SUB_TYPE_DICT = {
  36. 0: "草稿",
  37. 10: "提交",
  38. 20: "待审批",
  39. 21: "审批通过",
  40. 22: "审批不通过",
  41. 30: "重新提交"
  42. }
  43. # 信息发布分页(我能看的内容,小屏)
  44. @router.get('/list')
  45. async def get_publish_list(
  46. search_keyword: str = Query('', description='信息内容'),
  47. info_type: str = Query('', description='类型'),
  48. page: int = Query(1, gt=0, description='页码'),
  49. begin_time_s: str = Query(None, description='开始时间'),
  50. end_time_s: str = Query(None, description='结束时间'),
  51. info_order: str = Query("desc", description='时间排序'),
  52. page_size: int = Query(10, gt=0, description='pageSize'),
  53. db: Session = Depends(get_db),
  54. user_id = Depends(valid_access_token)
  55. ):
  56. try:
  57. # 应用查询条件
  58. where = and_(InfoPublishBase.del_flag == '0', InfoPublishBase.publish_status == 4)
  59. if search_keyword != '':
  60. where = and_(where, InfoPublishBase.content.like('%{}%'.format(search_keyword)))
  61. if info_type != '':
  62. where = and_(where, InfoPublishBase.info_type == info_type)
  63. if begin_time_s != None:
  64. begin_time = datetime.strptime(begin_time_s, "%Y-%m-%d")
  65. where = and_(where, InfoPublishBase.publish_time >= begin_time)
  66. if end_time_s != None:
  67. end_time = datetime.strptime(end_time_s, "%Y-%m-%d") + timedelta(days=1)
  68. where = and_(where, InfoPublishBase.publish_time < end_time)
  69. print(where)
  70. subquery = db.query(InfoPublishResponses.publish_id).filter(InfoPublishResponses.user_id == user_id).subquery()
  71. # 计算总条目数
  72. q = db.query(func.count(InfoPublishBase.id))
  73. q = q.filter(where).filter(InfoPublishBase.id == subquery.c.publish_id)
  74. total = q.scalar()
  75. # 执行分页查询
  76. q = db.query(InfoPublishBase)
  77. q = q.filter(where).filter(InfoPublishBase.id == subquery.c.publish_id)
  78. if info_order == 'desc':
  79. q.order_by(InfoPublishBase.publish_time.desc())
  80. if info_order == 'asc':
  81. q.order_by(InfoPublishBase.publish_time.asc())
  82. rows = q.offset((page - 1) * page_size).limit(page_size).all()
  83. data = []
  84. for row in rows:
  85. # 发布申请人
  86. recorded_by = row.recorded_by
  87. user_row = db.query(SysUser).filter(SysUser.user_id == recorded_by).first()
  88. nick_name = ""
  89. dept_name = ""
  90. if user_row is not None:
  91. nick_name = user_row.nick_name
  92. dept_id = user_row.dept_id
  93. dept_row = db.query(SysDept).filter(SysDept.dept_id == dept_id).first()
  94. if dept_row is not None:
  95. dept_name = dept_row.dept_name
  96. # 待处理人
  97. examine_user = "无"
  98. examine_by = row.examine_by
  99. user_row = db.query(SysUser).filter(SysUser.user_id == examine_by).first()
  100. if user_row is not None:
  101. examine_user = user_row.nick_name
  102. data.append({
  103. "id": row.id,
  104. "title": row.title,
  105. "info_type": row.info_type,
  106. "publish_group": row.publish_group,
  107. "content": row.content,
  108. "publish_time": get_datetime_str(row.publish_time),
  109. "add_time": row.add_time.strftime("%Y-%m-%d %H:%M"),
  110. "publish_channel": row.publish_channel,
  111. "nick_name": nick_name,
  112. "dept_name": dept_name,
  113. "examine_user": examine_user,
  114. "publish_status": db_dict.get_dict_label(db, "mm_publish_status", row.publish_status),
  115. "examine_status": db_dict.get_dict_label(db, "mm_examine_status", row.examine_status),
  116. "user_count": row.user_count,
  117. "user_ok_count": row.user_ok_count,
  118. "user_err_count": row.user_err_count,
  119. "user_sending_count": row.user_sending_count,
  120. "is_my_edit": (row.examine_status == 0 or row.examine_status == 9) and row.recorded_by == user_id, # 是否我的编辑事项
  121. "is_my_examine": row.examine_status == 1 and int(row.examine_by) == user_id # 是否我的审批事项
  122. })
  123. # 返回结果
  124. return {
  125. "code": 200,
  126. "msg": "查询成功",
  127. "data": data,
  128. "total": total
  129. }
  130. except Exception as e:
  131. # 处理异常
  132. traceback.print_exc()
  133. raise HTTPException(status_code=500, detail=str(e))
  134. @router.get('/detail')
  135. async def get_info_detail(
  136. request: Request,
  137. id: str = Query(None, description='信息编号'),
  138. db: Session = Depends(get_db),
  139. user_id = Depends(valid_access_token)):
  140. try:
  141. # 构建查询
  142. query = db.query(InfoPublishBase)
  143. query = query.filter(InfoPublishBase.id == id)
  144. # 执行查询
  145. row = query.first()
  146. if row is not None:
  147. # 发布申请人
  148. recorded_by = row.recorded_by
  149. user_row = db.query(SysUser).filter(SysUser.user_id == recorded_by).first()
  150. nick_name = ""
  151. dept_name = ""
  152. if user_row is not None:
  153. nick_name = user_row.nick_name
  154. dept_id = user_row.dept_id
  155. dept_row = db.query(SysDept).filter(SysDept.dept_id == dept_id).first()
  156. if dept_row is not None:
  157. dept_name = dept_row.dept_name
  158. response_row = db.query(InfoPublishResponses).filter(and_(InfoPublishResponses.publish_id == id, InfoPublishResponses.user_id == user_id)).first()
  159. # 是否我的审批事项(待审批)
  160. is_my_examine = 0
  161. 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()).first()
  162. if examine_row is not None:
  163. is_my_examine = 1
  164. data = {
  165. "id": row.id,
  166. "title": row.title,
  167. "info_type": row.info_type,
  168. "add_time": row.add_time.strftime("%Y-%m-%d %H:%M"),
  169. "nick_name": nick_name,
  170. "dept_name": dept_name,
  171. "publish_group": row.publish_group,
  172. "content": row.content,
  173. "publish_time": get_datetime_str(row.publish_time),
  174. "publish_channel": row.publish_channel,
  175. "response_type": response_row.response_type,
  176. "response_status": response_row.response_status,
  177. "response_time": get_datetime_str(response_row.response_time),
  178. "signature": get_signature_base64(db, response_row.id),
  179. "is_my_examine": is_my_examine
  180. }
  181. # 附件
  182. rows = db.query(InfoPublishFile).filter(and_(InfoPublishFile.from_scenario=="infopublish_attach_file", InfoPublishFile.foreign_key == id, InfoPublishFile.del_flag == '0')).all()
  183. data['files'] = [
  184. {
  185. "name": row.file_name,
  186. "url": row.storage_file_name
  187. }
  188. for row in rows
  189. ]
  190. # 审批进度
  191. data["examines"] = []
  192. rows = db.query(InfoPublishExamine).filter(InfoPublishExamine.publish_id == id).filter(InfoPublishExamine.del_flag == '0').all()
  193. for row in rows:
  194. data["examines"].append({
  195. "examine_type": EXAMINE_TYPE_DICT[row.examine_type],
  196. "examine_sub_type": EXAMINE_SUB_TYPE_DICT[row.examine_sub_type],
  197. "content": row.content,
  198. "examine_time": get_datetime_str(row.examine_time),
  199. "user_id": row.user_id,
  200. "user_name": row.user_name,
  201. "nick_name": row.nick_name
  202. })
  203. return {
  204. "code": 200,
  205. "msg": "查询成功",
  206. "data": data
  207. }
  208. else:
  209. return {
  210. "code": 500,
  211. "msg": "查询失败"
  212. }
  213. except Exception as e:
  214. # 处理异常
  215. traceback.print_exc()
  216. raise HTTPException(status_code=500, detail=str(e))
  217. @router.post("/confirmReceived")
  218. async def confirmReceived(
  219. request: Request,
  220. body = Depends(remove_xss_json),
  221. db: Session = Depends(get_db),
  222. user_id = Depends(valid_access_token)):
  223. try:
  224. id = get_req_param(body, "id")
  225. row = db.query(InfoPublishResponses).filter(and_(InfoPublishResponses.publish_id == id, InfoPublishResponses.user_id == user_id)).first()
  226. if row is None:
  227. return {
  228. "code": 500,
  229. "msg": "查询失败"
  230. }
  231. row.response_time = datetime.now()
  232. row.response_status = 1 # 已确认
  233. db.commit()
  234. return {
  235. "code": 200,
  236. "msg": "反馈成功",
  237. "data": {
  238. "response_status": row.response_status
  239. }
  240. }
  241. except Exception as e:
  242. # 处理异常
  243. traceback.print_exc()
  244. raise HTTPException(status_code=500, detail=str(e))
  245. # 确定签名
  246. @router.post("/confirmSignature")
  247. async def confirmSignature(
  248. request: Request,
  249. body = Depends(remove_xss_json),
  250. db: Session = Depends(get_db),
  251. user_id = Depends(valid_access_token)):
  252. try:
  253. id = get_req_param(body, "id")
  254. row = db.query(InfoPublishResponses).filter(and_(InfoPublishResponses.publish_id == id, InfoPublishResponses.user_id == user_id)).first()
  255. if row is None:
  256. return {
  257. "code": 500,
  258. "msg": "查询失败"
  259. }
  260. response_id = row.id
  261. file_name = new_guid() + ".png"
  262. file_path = f'/data/upload/mergefile/uploads/{file_name}'
  263. base64_data = get_req_param(body, "image")
  264. base64_data = base64_data.replace("data:image/png;base64,", "")
  265. binary_data = base64.b64decode(base64_data)
  266. bytes_io = BytesIO(binary_data)
  267. image = Image.open(bytes_io)
  268. image.save(file_path)
  269. new_file = InfoPublishFile(
  270. file_name="信息阅读确认签名.png",
  271. storage_file_name=file_name,
  272. file_path=f'/data/upload/mergefile/uploads/{file_name}',
  273. file_size=os.path.getsize(f'/data/upload/mergefile/uploads/{file_name}'),
  274. foreign_key=str(response_id),
  275. from_scenario="infopublish_signature_file",
  276. update_time=datetime.now(),
  277. create_time=datetime.now(),
  278. create_by=user_id,
  279. create_dept=0,
  280. del_flag='0',
  281. status=0,
  282. )
  283. db.add(new_file)
  284. row.response_time = datetime.now()
  285. row.response_status = 2 # 已签名
  286. db.commit()
  287. return {
  288. "code": 200,
  289. "msg": "反馈成功",
  290. "data": {
  291. "response_status": row.response_status
  292. }
  293. }
  294. except Exception as e:
  295. # 处理异常
  296. traceback.print_exc()
  297. raise HTTPException(status_code=500, detail=str(e))
  298. def image2base64(img_file: str):
  299. f = open(img_file, 'rb')
  300. img_raw_data = f.read()
  301. f.close()
  302. img_b64_string = base64.b64encode(img_raw_data)
  303. return img_b64_string.decode('ascii')
  304. def get_signature_base64(db: Session, response_id: int):
  305. row = db.query(InfoPublishFile).filter(and_(InfoPublishFile.from_scenario == 'infopublish_signature_file', InfoPublishFile.foreign_key == str(response_id))).first()
  306. if row is None:
  307. return ""
  308. return "data:image/png;base64," + image2base64(row.file_path)
  309. # 我的工作审批
  310. @router.get("/work_approval/list")
  311. async def work_approval_list(
  312. search_keyword: str = Query('', description='信息内容'),
  313. status: str = Query('1', description='状态'),
  314. info_type: str = Query(None, description='信息类型'),
  315. time_type: str = Query(None, description='时间类型'),
  316. info_order: str = Query("desc", description='时间排序'),
  317. page: int = Query(1, gt=0, description='页码'),
  318. page_size: int = Query(10, gt=0, description='pageSize'),
  319. db: Session = Depends(get_db),
  320. user_id = Depends(valid_access_token)
  321. ):
  322. try:
  323. # 应用查询条件
  324. where = and_(InfoPublishBase.del_flag == '0')
  325. # 待办
  326. if status == "1":
  327. subquery = db.query(InfoPublishExamine.publish_id).filter(InfoPublishExamine.del_flag == "0").filter(InfoPublishExamine.user_id == user_id).filter(InfoPublishExamine.examine_sub_type == 20).subquery()
  328. where = and_(where, InfoPublishBase.id == subquery.c.publish_id)
  329. # 已完成
  330. if status == "2":
  331. 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()
  332. where = and_(where, InfoPublishBase.id == subquery.c.publish_id)
  333. if search_keyword != '':
  334. where = and_(where, InfoPublishBase.content.like('%{}%'.format(search_keyword)))
  335. if info_type != None:
  336. where = and_(where, InfoPublishBase.info_type == info_type)
  337. '''
  338. if end_time_s != None:
  339. end_time = datetime.strptime(end_time_s, "%Y-%m-%d") + timedelta(days=1)
  340. where = and_(where, InfoPublishBase.publish_time < end_time)
  341. print(where)
  342. '''
  343. # subquery = db.query(InfoPublishResponses.publish_id).filter(InfoPublishResponses.user_id == user_id).subquery()
  344. # 计算总条目数
  345. q = db.query(func.count(InfoPublishBase.id)).filter(where)
  346. # q = q.filter(where).filter(InfoPublishBase.id == subquery.c.publish_id)
  347. total = q.scalar()
  348. # 执行分页查询
  349. q = db.query(InfoPublishBase).filter(where)
  350. # q = q.filter(where).filter(InfoPublishBase.id == subquery.c.publish_id)
  351. if info_order == 'desc':
  352. q.order_by(InfoPublishBase.add_time.desc())
  353. if info_order == 'asc':
  354. q.order_by(InfoPublishBase.add_time.asc())
  355. rows = q.offset((page - 1) * page_size).limit(page_size).all()
  356. data = []
  357. for row in rows:
  358. # 发布申请人
  359. recorded_by = row.recorded_by
  360. user_row = db.query(SysUser).filter(SysUser.user_id == recorded_by).first()
  361. nick_name = ""
  362. dept_name = ""
  363. if user_row is not None:
  364. nick_name = user_row.nick_name
  365. dept_id = user_row.dept_id
  366. dept_row = db.query(SysDept).filter(SysDept.dept_id == dept_id).first()
  367. if dept_row is not None:
  368. dept_name = dept_row.dept_name
  369. # 待处理人
  370. examine_user = "无"
  371. examine_by = row.examine_by
  372. user_row = db.query(SysUser).filter(SysUser.user_id == examine_by).first()
  373. if user_row is not None:
  374. examine_user = user_row.nick_name
  375. # 是否我的审批事项(待审批)
  376. is_my_examine = 0
  377. 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()
  378. if examine_row is not None:
  379. is_my_examine = 1
  380. data.append({
  381. "id": row.id,
  382. "title": row.title,
  383. "info_type": row.info_type,
  384. "publish_group": row.publish_group,
  385. "content": row.content,
  386. "publish_time": get_datetime_str(row.publish_time),
  387. "add_time": row.add_time.strftime("%Y-%m-%d %H:%M"),
  388. "publish_channel": row.publish_channel,
  389. "nick_name": nick_name,
  390. "dept_name": dept_name,
  391. "examine_user": examine_user,
  392. "publish_status": db_dict.get_dict_label(db, "mm_publish_status", row.publish_status),
  393. "examine_status": db_dict.get_dict_label(db, "mm_examine_status", row.examine_status),
  394. "user_count": row.user_count,
  395. "user_ok_count": row.user_ok_count,
  396. "user_err_count": row.user_err_count,
  397. "user_sending_count": row.user_sending_count,
  398. "is_my_edit": (row.examine_status == 0 or row.examine_status == 9) and row.recorded_by == user_id, # 是否我的编辑事项
  399. "is_my_examine": is_my_examine
  400. })
  401. # 返回结果
  402. return {
  403. "code": 200,
  404. "msg": "查询成功",
  405. "data": data,
  406. "total": total
  407. }
  408. except Exception as e:
  409. # 处理异常
  410. traceback.print_exc()
  411. raise HTTPException(status_code=500, detail=str(e))
  412. @router.get('/work_approval/detail')
  413. async def get_info_detail(
  414. request: Request,
  415. id: str = Query(None, description='信息编号'),
  416. db: Session = Depends(get_db),
  417. user_id = Depends(valid_access_token)):
  418. try:
  419. # 构建查询
  420. query = db.query(InfoPublishBase)
  421. query = query.filter(InfoPublishBase.id == id)
  422. # 执行查询
  423. row = query.first()
  424. if row is not None:
  425. # 发布申请人
  426. recorded_by = row.recorded_by
  427. user_row = db.query(SysUser).filter(SysUser.user_id == recorded_by).first()
  428. nick_name = ""
  429. dept_name = ""
  430. if user_row is not None:
  431. nick_name = user_row.nick_name
  432. dept_id = user_row.dept_id
  433. dept_row = db.query(SysDept).filter(SysDept.dept_id == dept_id).first()
  434. if dept_row is not None:
  435. dept_name = dept_row.dept_name
  436. # 是否我的审批事项(待审批)
  437. is_my_examine = 0
  438. 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()).first()
  439. if examine_row is not None:
  440. is_my_examine = 1
  441. data = {
  442. "id": row.id,
  443. "title": row.title,
  444. "info_type": row.info_type,
  445. "add_time": row.add_time.strftime("%Y-%m-%d %H:%M"),
  446. "nick_name": nick_name,
  447. "dept_name": dept_name,
  448. "publish_group": row.publish_group,
  449. "content": row.content,
  450. "publish_time": get_datetime_str(row.publish_time),
  451. "publish_channel": row.publish_channel,
  452. "is_my_examine": is_my_examine
  453. }
  454. # 附件
  455. rows = db.query(InfoPublishFile).filter(and_(InfoPublishFile.from_scenario=="infopublish_attach_file", InfoPublishFile.foreign_key == id, InfoPublishFile.del_flag == '0')).all()
  456. data['files'] = [
  457. {
  458. "name": row.file_name,
  459. "url": row.storage_file_name
  460. }
  461. for row in rows
  462. ]
  463. # 审批进度
  464. data["examines"] = []
  465. rows = db.query(InfoPublishExamine).filter(InfoPublishExamine.publish_id == id).filter(InfoPublishExamine.del_flag == '0').all()
  466. for row in rows:
  467. data["examines"].append({
  468. "examine_type": EXAMINE_TYPE_DICT[row.examine_type],
  469. "examine_sub_type": EXAMINE_SUB_TYPE_DICT[row.examine_sub_type],
  470. "content": row.content,
  471. "examine_time": get_datetime_str(row.examine_time),
  472. "user_id": row.user_id,
  473. "user_name": row.user_name,
  474. "nick_name": row.nick_name
  475. })
  476. return {
  477. "code": 200,
  478. "msg": "查询成功",
  479. "data": data
  480. }
  481. else:
  482. return {
  483. "code": 500,
  484. "msg": "查询失败"
  485. }
  486. except Exception as e:
  487. # 处理异常
  488. traceback.print_exc()
  489. raise HTTPException(status_code=500, detail=str(e))
  490. # 审批确认
  491. @router.post("/work_approval/confirm")
  492. async def work_approval_confirm(
  493. request: Request,
  494. body = Depends(remove_xss_json),
  495. db: Session = Depends(get_db),
  496. user_id = Depends(valid_access_token)):
  497. try:
  498. info_id = get_req_param(body, "info_id")
  499. action = get_req_param(body, "action")
  500. content = get_req_param(body, "content")
  501. return {
  502. "code": 200,
  503. "msg": "审批成功",
  504. "data": action
  505. }
  506. except Exception as e:
  507. # 处理异常
  508. traceback.print_exc()
  509. raise HTTPException(status_code=500, detail=str(e))