me.py 17 KB

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