call.py 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. from fastapi import APIRouter, Request, Depends, Query, HTTPException
  4. from fastapi.responses import FileResponse, StreamingResponse
  5. from database import get_db
  6. from sqlalchemy import text, exists, and_, or_, not_
  7. from sqlalchemy.orm import Session
  8. from sqlalchemy.sql import func
  9. from models import *
  10. import uuid
  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_user, db_yzy, db_dept, db_msg_center
  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 exceptions import AppException
  26. from typing import List, Dict,Set
  27. import openpyxl
  28. from io import BytesIO
  29. router = APIRouter()
  30. @router.get("/dept_by_key", response_model=Dict)
  31. def dept_by_key(db: Session = Depends(get_db), area_name: str = Query(None), keyword: str = Query(None)):
  32. def get_dept_tree(db: Session, dept_id: int):
  33. dept = db.query(SysDept).filter(SysDept.dept_id == dept_id).first()
  34. if not dept:
  35. return None
  36. children = []
  37. for child in db.query(SysDept).filter(SysDept.parent_id == dept.dept_id).all():
  38. child = get_dept_tree(db, child.dept_id)
  39. if child is not None:
  40. children.append(child)
  41. dept_info = {
  42. "uuid":str(uuid.uuid4()).replace('-',''),
  43. "id": dept.dept_id,
  44. "label": dept.dept_name,
  45. "deptType": True
  46. }
  47. if len(children) > 0:
  48. dept_info["children"] = children
  49. return dept_info
  50. dept_id = db_dept.get_dept_id_by_name(db, area_name)
  51. if dept_id == 0:
  52. return {
  53. "code": 200,
  54. "msg": "成功",
  55. "data": []
  56. }
  57. print('dept_id:', dept_id)
  58. data = get_dept_tree(db, dept_id)
  59. return {
  60. "code": 200,
  61. "msg": "成功",
  62. "data": [data]
  63. }
  64. # 一键点名全市至区县
  65. @router.post("/create_by_city_to_area")
  66. async def create_by_city_to_area(
  67. db: Session = Depends(get_db),
  68. user_id = Depends(valid_access_token)
  69. ):
  70. current_date = datetime.now().date()
  71. current_time = datetime.now().time()
  72. try:
  73. # 过滤当前时间内的值班人员
  74. q = db.query(DutyShift).filter(func.char_length(DutyShift.area_code) <= 6)
  75. q = q.filter(DutyShift.shift_date == current_date)
  76. q = q.filter(DutyShift.shift_status == 0)
  77. q = q.filter(DutyShift.start_time < current_time).filter(DutyShift.end_time > current_time)
  78. rows = q.all()
  79. user_count = len(rows)
  80. if user_count == 0:
  81. raise AppException(500, "暂无相关值班人员信息")
  82. new_call = OnlineRollCallBase(
  83. call_type = 1,
  84. recorded_by = user_id,
  85. create_time = datetime.now(),
  86. del_flag = '0',
  87. call_status = 1,
  88. user_count = user_count,
  89. ack_count = 0,
  90. unack_count = user_count,
  91. remark = '',
  92. update_time = datetime.now()
  93. )
  94. db.add(new_call)
  95. db.commit()
  96. db.refresh(new_call)
  97. new_call_id = new_call.id
  98. dept_list = []
  99. for row in rows:
  100. shift_id = row.shift_id
  101. shift_dept_id = row.dept_id
  102. shift_dept_name = db_dept.get_dept_name_by_id(db, row.dept_id)
  103. leader_id = row.leader_id
  104. primary_staff_id = row.primary_staff_id
  105. secondary_staff_id = row.secondary_staff_id
  106. standby_staff_id = row.standby_staff_id
  107. onduty_user = db_user.get_nick_name_by_id(db, row.primary_staff_id)
  108. onduty_leader = db_user.get_nick_name_by_id(db, row.leader_id)
  109. video_url = "#"
  110. call_url = "#"
  111. # 避免同一个部门重复
  112. if shift_dept_id in dept_list:
  113. continue
  114. dept_list.append(shift_dept_id)
  115. new_detail = OnlineRollCallDetail(
  116. pid = new_call_id,
  117. shift_id = shift_id,
  118. dept_id = shift_dept_id,
  119. dept_name = shift_dept_name,
  120. onduty_user = onduty_user,
  121. onduty_leader = onduty_leader,
  122. video_url = video_url,
  123. call_url = call_url,
  124. ack_status = 0,
  125. ack_time = None,
  126. create_time = datetime.now(),
  127. del_flag = '0',
  128. ack_type = 0,
  129. leader_id = leader_id,
  130. primary_staff_id = primary_staff_id,
  131. secondary_staff_id = secondary_staff_id,
  132. standby_staff_id = standby_staff_id
  133. )
  134. db.add(new_detail)
  135. db.commit()
  136. db.refresh(new_detail)
  137. send_yzy_msg(db, new_detail, user_id)
  138. db_msg_center.add_msg(db, "在线点名", new_detail.id, user_id)
  139. return {
  140. "code": 200,
  141. "msg": "点名创建成功",
  142. "data": new_call_id
  143. }
  144. except AppException as e:
  145. return {
  146. "code": e.code,
  147. "msg": e.msg
  148. }
  149. except Exception as e:
  150. traceback.print_exc()
  151. # 处理异常
  152. raise HTTPException(status_code=500, detail=str(e))
  153. # 一键点名全市至镇街
  154. @router.post("/create_by_city_to_district")
  155. async def create_by_city_to_district(
  156. db: Session = Depends(get_db),
  157. user_id = Depends(valid_access_token)
  158. ):
  159. current_date = datetime.now().date()
  160. current_time = datetime.now().time()
  161. try:
  162. # 过滤当前时间内的值班人员
  163. q = db.query(DutyShift).filter(func.char_length(DutyShift.area_code) <= 9)
  164. q = q.filter(DutyShift.shift_date == current_date)
  165. q = q.filter(DutyShift.shift_status == 0)
  166. q = q.filter(DutyShift.start_time < current_time).filter(DutyShift.end_time > current_time)
  167. rows = q.all()
  168. user_count = len(rows)
  169. if user_count == 0:
  170. raise AppException(500, "暂无相关值班人员信息")
  171. new_call = OnlineRollCallBase(
  172. call_type = 1,
  173. recorded_by = user_id,
  174. create_time = datetime.now(),
  175. del_flag = '0',
  176. call_status = 1,
  177. user_count = user_count,
  178. ack_count = 0,
  179. unack_count = user_count,
  180. remark = '',
  181. update_time = datetime.now()
  182. )
  183. db.add(new_call)
  184. db.commit()
  185. db.refresh(new_call)
  186. new_call_id = new_call.id
  187. dept_list = []
  188. for row in rows:
  189. shift_id = row.shift_id
  190. shift_dept_id = row.dept_id
  191. shift_dept_name = db_dept.get_dept_name_by_id(db, row.dept_id)
  192. leader_id = row.leader_id
  193. primary_staff_id = row.primary_staff_id
  194. secondary_staff_id = row.secondary_staff_id
  195. standby_staff_id = row.standby_staff_id
  196. onduty_user = db_user.get_nick_name_by_id(db, row.primary_staff_id)
  197. onduty_leader = db_user.get_nick_name_by_id(db, row.leader_id)
  198. video_url = "#"
  199. call_url = "#"
  200. # 避免同一个部门重复
  201. if shift_dept_id in dept_list:
  202. continue
  203. dept_list.append(shift_dept_id)
  204. new_detail = OnlineRollCallDetail(
  205. pid = new_call_id,
  206. shift_id = shift_id,
  207. dept_id = shift_dept_id,
  208. dept_name = shift_dept_name,
  209. onduty_user = onduty_user,
  210. onduty_leader = onduty_leader,
  211. video_url = video_url,
  212. call_url = call_url,
  213. ack_status = 0,
  214. ack_time = None,
  215. create_time = datetime.now(),
  216. del_flag = '0',
  217. ack_type = 0,
  218. leader_id = leader_id,
  219. primary_staff_id = primary_staff_id,
  220. secondary_staff_id = secondary_staff_id,
  221. standby_staff_id = standby_staff_id
  222. )
  223. db.add(new_detail)
  224. db.commit()
  225. return {
  226. "code": 200,
  227. "msg": "点名创建成功",
  228. "data": new_call_id
  229. }
  230. except AppException as e:
  231. return {
  232. "code": e.code,
  233. "msg": e.msg
  234. }
  235. except Exception as e:
  236. traceback.print_exc()
  237. # 处理异常
  238. raise HTTPException(status_code=500, detail=str(e))
  239. # 新建点名(分区/县点名)
  240. @router.post("/create_by_dept_ids")
  241. async def create_by_dept_ids(
  242. db: Session = Depends(get_db),
  243. body = Depends(remove_xss_json),
  244. user_id = Depends(valid_access_token)
  245. ):
  246. current_date = datetime.now().date()
  247. current_time = datetime.now().time()
  248. try:
  249. if len(body['depts']) == 0:
  250. raise AppException(500, "请勾选部门")
  251. new_call = OnlineRollCallBase(
  252. call_type = 3,
  253. recorded_by = user_id,
  254. create_time = datetime.now(),
  255. del_flag = '0',
  256. call_status = 1,
  257. user_count = 0,
  258. ack_count = 0,
  259. unack_count = 0,
  260. remark = body['remark'],
  261. update_time = datetime.now()
  262. )
  263. db.add(new_call)
  264. db.commit()
  265. db.refresh(new_call)
  266. new_call_id = new_call.id
  267. for dept_id in body['depts']:
  268. # 过滤当前时间内的值班人员
  269. q = db.query(DutyShift).filter(DutyShift.dept_id == dept_id)
  270. q = q.filter(DutyShift.shift_date == current_date)
  271. q = q.filter(DutyShift.shift_status == 0)
  272. q = q.filter(DutyShift.start_time < current_time).filter(DutyShift.end_time > current_time)
  273. row = q.first()
  274. if row is not None:
  275. print(dept_id)
  276. shift_id = row.shift_id
  277. shift_dept_id = row.dept_id
  278. shift_dept_name = db_dept.get_dept_name_by_id(db, row.dept_id)
  279. leader_id = row.leader_id
  280. primary_staff_id = row.primary_staff_id
  281. secondary_staff_id = row.secondary_staff_id
  282. standby_staff_id = row.standby_staff_id
  283. onduty_user = db_user.get_nick_name_by_id(db, row.primary_staff_id)
  284. onduty_leader = db_user.get_nick_name_by_id(db, row.leader_id)
  285. video_url = "#"
  286. call_url = "#"
  287. new_detail = OnlineRollCallDetail(
  288. pid = new_call_id,
  289. shift_id = shift_id,
  290. dept_id = shift_dept_id,
  291. dept_name = shift_dept_name,
  292. onduty_user = onduty_user,
  293. onduty_leader = onduty_leader,
  294. video_url = video_url,
  295. call_url = call_url,
  296. ack_status = 0,
  297. ack_time = None,
  298. create_time = datetime.now(),
  299. del_flag = '0',
  300. ack_type = 0,
  301. leader_id = leader_id,
  302. primary_staff_id = primary_staff_id,
  303. secondary_staff_id = secondary_staff_id,
  304. standby_staff_id = standby_staff_id
  305. )
  306. db.add(new_detail)
  307. db.commit()
  308. # 检查多次,避免人员为空
  309. user_count = db.query(OnlineRollCallDetail).filter(OnlineRollCallDetail.pid == new_call_id).count()
  310. if user_count == 0:
  311. db.query(OnlineRollCallBase).filter(OnlineRollCallBase.id == new_call_id).delete()
  312. db.commit()
  313. raise AppException(500, "暂无相关值班人员信息")
  314. db.query(OnlineRollCallBase).filter(OnlineRollCallBase.id == new_call_id).update({"user_count": user_count, "unack_count": user_count})
  315. db.commit()
  316. return {
  317. "code": 200,
  318. "msg": "点名创建成功",
  319. "data": new_call_id
  320. }
  321. except AppException as e:
  322. return {
  323. "code": e.code,
  324. "msg": e.msg
  325. }
  326. except Exception as e:
  327. traceback.print_exc()
  328. # 处理异常
  329. raise HTTPException(status_code=500, detail=str(e))
  330. # 结束点名
  331. @router.post("/end")
  332. async def end_call(
  333. db: Session = Depends(get_db),
  334. body = Depends(remove_xss_json),
  335. user_id = Depends(valid_access_token)
  336. ):
  337. call_id = body['call_id']
  338. row = db.query(OnlineRollCallBase).filter(and_(OnlineRollCallBase.id == call_id, OnlineRollCallBase.del_flag == '0')).first()
  339. if row is None:
  340. return {
  341. "code": 500,
  342. "msg": "点名记录不存在"
  343. }
  344. if row.call_status != 1:
  345. return {
  346. "code": 500,
  347. "msg": "点名记录状态已结束"
  348. }
  349. row.end_time = datetime.now()
  350. row.call_status = 2 # 结束
  351. row.update_time = datetime.now()
  352. db.commit()
  353. return {
  354. "code": 200,
  355. "msg": "点名结束成功"
  356. }
  357. # 标记用户已应答
  358. @router.post("/ack")
  359. async def ack_all(
  360. db: Session = Depends(get_db),
  361. body = Depends(remove_xss_json),
  362. user_id = Depends(valid_access_token)
  363. ):
  364. call_id = body['call_id']
  365. base_row = db.query(OnlineRollCallBase).filter(OnlineRollCallBase.id == call_id).first()
  366. if base_row is None:
  367. return {
  368. "code": 500,
  369. "msg": "点名记录不存在"
  370. }
  371. detail_row = db.query(OnlineRollCallDetail).filter(and_(OnlineRollCallDetail.pid == call_id, OnlineRollCallDetail.leader_id == user_id)).first()
  372. if detail_row is None:
  373. return {
  374. "code": 500,
  375. "msg": "点名记录不存在!"
  376. }
  377. detail_row.ack_status = 1 # 已应答
  378. detail_row.ack_time = datetime.now()
  379. db.commit()
  380. # 统计应答数
  381. ack_count = db.query(OnlineRollCallDetail).filter(and_(OnlineRollCallDetail.pid == call_id, OnlineRollCallDetail.ack_status == 1)).count()
  382. # 统计未应答数
  383. unack_count = db.query(OnlineRollCallDetail).filter(and_(OnlineRollCallDetail.pid == call_id, OnlineRollCallDetail.ack_status == 2)).count()
  384. db.query(OnlineRollCallBase).filter(OnlineRollCallBase.id == call_id).update({
  385. "ack_count": ack_count, "unack_count": unack_count, "update_time": datetime.now()
  386. })
  387. db.commit()
  388. return {
  389. "code": 200,
  390. "msg": "应答成功"
  391. }
  392. # 查询是否有我的待应答记录(提醒)
  393. @router.post("/mycall")
  394. async def query_mycall(
  395. db: Session = Depends(get_db),
  396. user_id = Depends(valid_access_token)
  397. ):
  398. rows = db.query(OnlineRollCallDetail).filter(and_(OnlineRollCallDetail.leader_id == user_id, OnlineRollCallDetail.ack_status == 0)).all()
  399. data = []
  400. for row in rows:
  401. call_id = row.pid
  402. base_row = db.query(OnlineRollCallBase).filter(and_(OnlineRollCallBase.id == call_id, OnlineRollCallBase.call_status == 1, OnlineRollCallBase.del_flag == '0')).first()
  403. if base_row is not None:
  404. data.append({
  405. "id": call_id,
  406. "time1": get_datetime_str(base_row.create_time)
  407. })
  408. return {
  409. "code": 200,
  410. "msg": "查询成功",
  411. "data": data,
  412. "total": len(data)
  413. }
  414. #应答详情
  415. @router.get('/detail')
  416. async def get_event_detail(
  417. request: Request,
  418. call_id: str = Query(None, description='点名ID'),
  419. db: Session = Depends(get_db)):
  420. try:
  421. base_row = db.query(OnlineRollCallBase).filter(OnlineRollCallBase.id == call_id).first()
  422. if base_row is None:
  423. return {
  424. "code": 500,
  425. "msg": "点名记录不存在"
  426. }
  427. data = get_model_dict(base_row)
  428. data['begin_time'] = get_datetime_str(data['create_time'])
  429. data['update_time'] = get_datetime_str(data['update_time'])
  430. data['duration_time'] = ''
  431. # 已应答(结束)
  432. if data['call_status'] == 2:
  433. # 处理垃圾数据
  434. if base_row.end_time is None:
  435. base_row.end_time = datetime.now()
  436. db.commit()
  437. time_diff = base_row.end_time - base_row.create_time
  438. # hours,minutes,seconds = str(time_diff).split(':')
  439. data['duration_time'] = str(time_diff)
  440. detail_rows = db.query(OnlineRollCallDetail).filter(OnlineRollCallDetail.pid == call_id).all()
  441. items = []
  442. for row in detail_rows:
  443. detail_info = get_model_dict(row)
  444. detail_info['begin_time'] = get_datetime_str(detail_info['create_time'])
  445. detail_info['ack_time'] = get_datetime_str(detail_info['ack_time'])
  446. detail_info['ack_status_text'] = get_ack_status_text(detail_info['ack_status'])
  447. items.append(detail_info)
  448. data['items'] = items
  449. return {
  450. "code": 200,
  451. "msg": "查询成功",
  452. "data": data
  453. }
  454. except Exception as e:
  455. # 处理异常
  456. traceback.print_exc()
  457. raise HTTPException(status_code=500, detail=str(e))
  458. def send_yzy_msg(db: Session, detail_entity: OnlineRollCallDetail, user_id: int) -> None:
  459. to_user_id = detail_entity.leader_id
  460. user_info = db_user.get_user_info(db, to_user_id)
  461. yzy_account = user_info.yzy_account
  462. yzy_userid = db_yzy.get_userid_by_account(db, yzy_account)
  463. create_time = get_datetime_str(detail_entity.create_time)
  464. detail_url = YzyApi.format_redirect_url("{}/".format(settings.YJXP_WEB_ROOT_PATH)) # 主页
  465. description = f"你有一条在线点名通知,请尽快确认\n点名时间:{create_time}"
  466. data = {
  467. "yzy_userid": yzy_userid,
  468. "mobile": yzy_account,
  469. "content": description,
  470. "recorded_by": user_id,
  471. "detail_url": detail_url,
  472. "foreign_key": detail_entity.id,
  473. "from_scenario": "online_roll_call_detail",
  474. "title": "在线点名提醒"
  475. }
  476. YzyApi.add_to_msg_queue(db, data)
  477. def get_ack_status_text(ack_status: int) -> str:
  478. if ack_status == 0:
  479. return '未应答'
  480. elif ack_status == 1:
  481. return '已接通'
  482. elif ack_status == 2:
  483. return '呼叫中'
  484. else:
  485. return str(ack_status)
  486. #应答详情
  487. @router.get('/list')
  488. async def get_event_list(
  489. request: Request,
  490. begin_date: str = Query('', description='开始时间'),
  491. end_date: str = Query('', description='结束时间'),
  492. page: int = Query(1, gt=0, description='页码'),
  493. page_size: int = Query(10, gt=0, description='pageSize'),
  494. db: Session = Depends(get_db)):
  495. try:
  496. # 两周内
  497. d1 = datetime.now() - timedelta(days=14)
  498. where = and_(OnlineRollCallBase.del_flag == '0', OnlineRollCallBase.create_time > d1)
  499. if begin_date is not None and begin_date != '':
  500. begin_date = datetime.strptime(begin_date, "%Y-%m-%d")
  501. where = and_(where, OnlineRollCallBase.create_time > begin_date)
  502. if end_date is not None and end_date != '':
  503. end_date = datetime.strptime(end_date, "%Y-%m-%d") + timedelta(days=1)
  504. where = and_(where, OnlineRollCallBase.create_time < end_date)
  505. print(where)
  506. # 计算总条目数
  507. q = db.query(func.count(OnlineRollCallBase.id))
  508. q = q.filter(where)
  509. total = q.scalar()
  510. # 执行分页查询
  511. q = db.query(OnlineRollCallBase)
  512. q = q.filter(where)
  513. rows = q.order_by(OnlineRollCallBase.id.desc()).offset((page - 1) * page_size).limit(page_size).all()
  514. data = []
  515. for row in rows:
  516. duration_time = ""
  517. # 已结束
  518. if row.call_status == 2:
  519. time_diff = row.end_time - row.create_time
  520. # hours,minutes,seconds = str(time_diff).split(':')
  521. duration_time = str(time_diff)
  522. data.append({
  523. "id": row.id,
  524. "begin_time": get_datetime_str(row.create_time),
  525. "end_time": get_datetime_str(row.end_time),
  526. "duration_time": duration_time,
  527. "call_status": row.call_status,
  528. "ack_count": row.ack_count,
  529. "unack_count": row.unack_count
  530. })
  531. # 返回结果
  532. return {
  533. "code": 200,
  534. "msg": "查询成功",
  535. "data": data,
  536. "total": total
  537. }
  538. except Exception as e:
  539. # 处理异常
  540. traceback.print_exc()
  541. raise HTTPException(status_code=500, detail=str(e))
  542. #应答列表(我的)
  543. @router.get('/ack_list')
  544. async def get_event_list(
  545. request: Request,
  546. begin_date: str = Query('', description='开始时间'),
  547. end_date: str = Query('', description='结束时间'),
  548. page: int = Query(1, gt=0, description='页码'),
  549. page_size: int = Query(10, gt=0, description='pageSize'),
  550. db: Session = Depends(get_db),
  551. user_id = Depends(valid_access_token)
  552. ):
  553. try:
  554. where = and_(OnlineRollCallDetail.leader_id == user_id, OnlineRollCallDetail.del_flag == '0')
  555. if begin_date is not None and begin_date != '':
  556. begin_date = datetime.strptime(begin_date, "%Y-%m-%d")
  557. where = and_(where, OnlineRollCallDetail.create_time > begin_date)
  558. if end_date is not None and end_date != '':
  559. end_date = datetime.strptime(end_date, "%Y-%m-%d") + timedelta(days=1)
  560. where = and_(where, OnlineRollCallDetail.create_time < end_date)
  561. print(where)
  562. # 计算总条目数
  563. q = db.query(func.count(OnlineRollCallDetail.id))
  564. q = q.filter(where)
  565. total = q.scalar()
  566. # 执行分页查询
  567. q = db.query(OnlineRollCallDetail)
  568. q = q.filter(where)
  569. rows = q.order_by(OnlineRollCallDetail.id.desc()).offset((page - 1) * page_size).limit(page_size).all()
  570. data = []
  571. for row in rows:
  572. duration_time = ""
  573. # 已应答
  574. if row.ack_status == 1:
  575. time_diff = row.ack_time - row.create_time
  576. if time_diff.days < 0:
  577. duration_time = "超过{}天".format(abs(time_diff.days))
  578. else:
  579. hours,minutes,seconds = str(time_diff).split(':')
  580. duration_time = str(time_diff)
  581. data.append({
  582. "id": row.id,
  583. "create_time": get_datetime_str(row.create_time),
  584. "duration_time": duration_time,
  585. "ack_status": row.ack_status
  586. })
  587. # 返回结果
  588. return {
  589. "code": 200,
  590. "msg": "查询成功",
  591. "data": data,
  592. "total": total
  593. }
  594. except Exception as e:
  595. # 处理异常
  596. traceback.print_exc()
  597. raise HTTPException(status_code=500, detail=str(e))
  598. # 点名统计(我的)
  599. @router.get("/summary")
  600. async def get_call_summary(request: Request,
  601. db: Session = Depends(get_db),
  602. user_id = Depends(valid_access_token)):
  603. try:
  604. call_count = db.query(OnlineRollCallDetail).filter(and_(OnlineRollCallDetail.leader_id == user_id, OnlineRollCallDetail.del_flag == '0')).count()
  605. ack_count = db.query(OnlineRollCallDetail).filter(and_(OnlineRollCallDetail.leader_id == user_id, OnlineRollCallDetail.del_flag == '0', OnlineRollCallDetail.ack_status == 1)).count()
  606. unack_count = db.query(OnlineRollCallDetail).filter(and_(OnlineRollCallDetail.leader_id == user_id, OnlineRollCallDetail.del_flag == '0', OnlineRollCallDetail.ack_status == 0)).count()
  607. data = {
  608. "call_count": call_count,
  609. "ack_count": ack_count,
  610. "unack_count": unack_count
  611. }
  612. return {
  613. "code": 200,
  614. "msg": "查询成功",
  615. "data": data
  616. }
  617. except Exception as e:
  618. # 处理异常
  619. traceback.print_exc()
  620. raise HTTPException(status_code=500, detail=str(e))
  621. @router.get("/export", response_class=FileResponse)
  622. async def get_export_xslx(
  623. request: Request,
  624. call_id: str,
  625. db: Session = Depends(get_db)):
  626. # 导出excel表
  627. wb = openpyxl.Workbook()
  628. ws = wb.active
  629. ws.cell(1, 1).value = "部门名称"
  630. ws.cell(1, 2).value = "值班领导"
  631. ws.cell(1, 3).value = "值班员"
  632. ws.cell(1, 4).value = "点名开始时间"
  633. ws.cell(1, 5).value = "应答状态"
  634. ws.cell(1, 6).value = "应答时间"
  635. q = db.query(OnlineRollCallDetail)
  636. q = q.filter(and_(OnlineRollCallDetail.pid == call_id, OnlineRollCallDetail.del_flag == '0')).order_by(OnlineRollCallDetail.ack_status.desc(), OnlineRollCallDetail.ack_time.asc())
  637. rows = q.all()
  638. excel_row = 2
  639. for row in rows:
  640. ws.cell(excel_row, 1).value = row.dept_name
  641. ws.cell(excel_row, 2).value = row.onduty_leader
  642. ws.cell(excel_row, 3).value = row.onduty_user
  643. ws.cell(excel_row, 4).value = get_datetime_str(row.create_time)
  644. ws.cell(excel_row, 5).value = get_ack_status_text(row.ack_status)
  645. ws.cell(excel_row, 6).value = get_datetime_str(row.ack_time)
  646. excel_row = excel_row + 1
  647. upload_path = '/data/download/mergefile'
  648. if os.path.exists(upload_path) == False:
  649. os.makedirs(upload_path)
  650. excel_file_name = new_guid() +".xlsx"
  651. save_path = os.path.join(upload_path, excel_file_name)
  652. wb.save(save_path)
  653. wb.close()
  654. return FileResponse(save_path)