瀏覽代碼

no message

libushang 6 月之前
父節點
當前提交
ae6c360151

+ 2 - 1
common/db/db_area.py

@@ -10,4 +10,5 @@ from utils import *
 
 # 根据经纬度获取地区代码
 def get_region_code_by_gps(db: Session, lng: str, lat: str):
-    return "4409"
+    return "4409"
+

+ 3 - 3
exceptions.py

@@ -19,10 +19,10 @@ class Common404Exception(Exception):
 
 
 class AppException(Exception):
-    def __init__(self, errcode: int, errmsg: str):
+    def __init__(self, code: int, msg: str):
         super().__init__()
-        self.errcode = errcode
-        self.errmsg = errmsg
+        self.code = code
+        self.msg = msg
 
 class AlertException(Exception):
     def __init__(self, ret: int, msg: str):

+ 2 - 0
jobs/yzy_job.py

@@ -18,6 +18,7 @@ def proc():
     if redis_lock(lock_key):
         logger.info(datetime.now())
 
+        '''
         redirect_url = "{}/leader/index".format(settings.YJXP_WEB_ROOT_PATH) # 业务页面
         detail_url = YzyApi.format_redirect_url(redirect_url, "eb4kehgy6wj4qn0jhx1dk6")
         
@@ -43,6 +44,7 @@ def proc():
             YzyApi.add_to_msg_queue(db, data)
         db.close()
 
+        '''
         redis_unlock(lock_key)
 
 def yzy_msg_queue_proc():

+ 2 - 1
models/__init__.py

@@ -18,4 +18,5 @@ from .geojson_base import *
 from .xxfb_base import *
 from .addressbook_base import *
 from .risk_management import *
-from .online_roll_call import *
+from .online_roll_call import *
+from .duty_base import *

+ 49 - 0
models/duty_base.py

@@ -0,0 +1,49 @@
+# -*- coding: utf-8 -*-
+from sqlalchemy import String, Column, Integer,DateTime,Text,BigInteger,Boolean,PrimaryKeyConstraint,Index,UniqueConstraint,CHAR,LargeBinary,TIMESTAMP
+from sqlalchemy.dialects.mysql import TINYINT
+from sqlalchemy.sql import func
+from database import Base
+from datetime import datetime
+
+class DutyShift(Base):
+    """
+    值班日历
+    """
+    __tablename__ = 'duty_shift'
+   
+    shift_id = Column(Integer, primary_key=True, autoincrement=True, comment='ID')
+    shift_date = Column(DateTime, nullable=False, comment="班次日期")
+    start_time = Column(DateTime, nullable=False, comment="开始时间")
+    end_time = Column(DateTime, nullable=False, comment="结束时间")
+    leader_id = Column(Integer, nullable=False, comment="领导ID")
+    primary_staff_id = Column(Integer, nullable=False, comment="主班人员ID")
+    secondary_staff_id = Column(Integer, nullable=False, comment="副班人员ID")
+    standby_staff_id = Column(Integer, nullable=False, comment="备班人员ID")
+
+    duty_type = Column(String, default='', server_default='', comment="值班类型")
+    shfit_status = Column(Integer, default='0', server_default='0', comment="值班状态 0 默认 1已交班")
+    handover_user_id = Column(Integer, comment="交班人员ID")
+    handover_time = Column(DateTime, comment="交班时间")
+    dept_id = Column(Integer, nullable=False, comment="部门ID")
+    area_code = Column(String, default='', server_default='', comment="行政区划代码")
+    
+    class Config:
+        orm_mode = True
+
+
+class DutyNotify(Base):
+    """
+    值班事项提醒
+    """
+    __tablename__ = 'duty_notify'
+   
+    id = Column(Integer, primary_key=True, autoincrement=True, comment='ID')
+    shift_id = Column(Integer, default='0', server_default='0', comment="班次ID")
+    notify_content = Column(String, default='', server_default='', comment="提示内容")
+    notify_type = Column(Integer, default='0', server_default='0', comment="1 待办事项 2 提醒事项")
+    create_time = Column(DateTime, default=datetime.now, comment='数据创建时间')
+    del_flag = Column(String(1), default='0', comment='删除标志(0代表存在 2代表删除)')
+    recorded_by = Column(Integer, default=0, server_default='0', comment='记录用户ID')
+
+    class Config:
+        orm_mode = True

+ 3 - 3
models/online_roll_call.py

@@ -14,6 +14,7 @@ class OnlineRollCallBase(Base):
     create_time = Column(DateTime, default=datetime.now, comment='数据创建时间')
     end_time = Column(DateTime, comment='结束时间')
     del_flag = Column(String(1), default='0', comment='删除标志(0代表存在 2代表删除)')
+    call_status = Column(Integer, default=0, server_default='0', comment='点名状态 1 进行中 2 已结束')
     user_count = Column(Integer, default=0, server_default='0', comment='用户数')
     ack_count = Column(Integer, default=0, server_default='0', comment='应答数')
     unack_count = Column(Integer, default=0, server_default='0', comment='未应答数')
@@ -32,15 +33,14 @@ class OnlineRollCallDetail(Base):
 
     id = Column(BigInteger, primary_key=True, autoincrement=True, comment='ID')
     pid = Column(BigInteger, default=0, server_default='0', comment='关联主表ID')
-    user_id = Column(Integer, default=0, server_default='0', comment='关联用户ID')
+    shift_id = Column(Integer, default=0, server_default='0', comment='值班ID')
     dept_id = Column(Integer, default=0, server_default='0', comment='关联用户所在部门ID')
-    nick_name = Column(String, default='', server_default='', comment='用户姓名')
     dept_name = Column(String, default='', server_default='', comment='部门名称')
     onduty_user = Column(String, default='', server_default='', comment='值班员(显示)')
     onduty_leader = Column(String, default='', server_default='', comment='值班领导(显示)')
     video_url = Column(String, default='', server_default='', comment='视频URL')
     call_url = Column(String, default='', server_default='', comment='电话URL')
-    ack_status = Column(Integer, default=0, server_default='0', comment='应答状态 0 未应答 1 已应答')
+    ack_status = Column(Integer, default=0, server_default='0', comment='应答状态 0 未应答 1 已接通 2 呼叫中')
     act_time = Column(DateTime, comment='应答时间')
     create_time = Column(DateTime, default=datetime.now, comment='数据创建时间')
     del_flag = Column(String(1), default='0', comment='删除标志(0代表存在 2代表删除)')

+ 1 - 0
routers/api/eventManagement/checkin.py

@@ -5,6 +5,7 @@ from fastapi.responses import JSONResponse
 from database import get_db
 from sqlalchemy import text, exists, and_, or_, not_
 from sqlalchemy.orm import Session
+from sqlalchemy.sql import func
 from models import *
 import json
 import random

+ 382 - 45
routers/api/onlineRollCall/call.py

@@ -5,13 +5,14 @@ from fastapi import APIRouter, Request, Depends, Query, HTTPException
 from database import get_db
 from sqlalchemy import text, exists, and_, or_, not_
 from sqlalchemy.orm import Session
+from sqlalchemy.sql import func
 from models import *
-import json
+import uuid
 import os
 from sqlalchemy import create_engine, select
 from typing import Optional
 from utils.StripTagsHTMLParser import *
-from common.db import db_event_management, db_user, db_area, db_emergency_plan
+from common.db import db_event_management, db_user, db_area, db_dept
 from common.security import valid_access_token
 import traceback
 from utils import *
@@ -21,34 +22,268 @@ from common.db import db_dict
 from urllib.parse import quote
 import base64
 from config import settings
+from exceptions import AppException
+from typing import List, Dict,Set
 
 router = APIRouter()
 
-@router.post("/create")
-async def create_all(
+@router.get("/dept_by_key", response_model=Dict)
+def dept_by_key(db: Session = Depends(get_db), area_name: str = Query(None), keyword: str = Query(None)):
+
+    current_date = datetime.now().date()
+    current_time  = datetime.now().time()
+
+    def get_dept_tree(db: Session, dept_id: int):
+        dept = db.query(SysDept).filter(SysDept.dept_id == dept_id).first()
+        if not dept:
+            return None
+        
+        children = []
+        for child in db.query(SysDept).filter(SysDept.parent_id == dept.dept_id).all():
+            child = get_dept_tree(db, child.dept_id)
+            if child is not None:
+                children.append(child)
+
+        # 获取值班信息
+        '''
+        q = db.query(DutyShift)
+        q = q.filter(DutyShift.shift_date == current_date)
+        q = q.filter(DutyShift.shfit_status == 0)
+        q = q.filter(DutyShift.start_time < current_time).filter(DutyShift.end_time > current_time)
+        shift_row = q.first()
+        if shift_row is not None:
+            children.append({
+                "uuid":str(uuid.uuid4()).replace('-',''),
+                "id": shift_row.shift_id,
+                "label": str(shift_row.shift_id),
+                "deptType": False
+            })
+        '''
+
+        dept_info = {
+            "uuid":str(uuid.uuid4()).replace('-',''),
+            "id": dept.dept_id,
+            "label": dept.dept_name,
+            "deptType": True
+        }
+        if len(children) > 0:
+            dept_info["children"] = children
+
+        return dept_info
+    
+    dept_id = db_dept.get_dept_id_by_name(db, area_name)
+    if dept_id == 0:
+        return {
+            "code": 200,
+            "msg": "成功",
+            "data": []
+        }
+    print('dept_id:', dept_id)
+    data =  get_dept_tree(db, dept_id)
+    return {
+        "code": 200,
+        "msg": "成功",
+        "data": [data]
+    }
+
+# 一键点名全市至区县
+@router.post("/create_by_city_to_area")
+async def create_by_city_to_area(
     db: Session = Depends(get_db),
-    body = Depends(remove_xss_json),
     user_id = Depends(valid_access_token)
 ):
+    current_date = datetime.now().date()
+    current_time  = datetime.now().time()
     try:
-        dept_id = 0
-        dept_name = ''
+        # 过滤当前时间内的值班人员
+        q = db.query(DutyShift).filter(func.char_length(DutyShift.area_code) <= 6)
+        q = q.filter(DutyShift.shift_date == current_date)
+        q = q.filter(DutyShift.shfit_status == 0)
+        q = q.filter(DutyShift.start_time < current_time).filter(DutyShift.end_time > current_time)
+        rows = q.all()
+        
+        user_count = len(rows)
+        if user_count == 0:
+            raise AppException(500, "暂无相关值班人员信息")
+
+        new_call = OnlineRollCallBase(
+            call_type = 1,
+            recorded_by = user_id,
+            create_time = datetime.now(),
+            del_flag = '0',
+            call_status = 1,
+            user_count = user_count,
+            ack_count = 0,
+            unack_count = user_count,
+            remark = '',
+            update_time = datetime.now()
+        )
+        db.add(new_call)
+        db.commit()
+        db.refresh(new_call)
+        new_call_id = new_call.id
+
+        dept_list = []
+        for row in rows:
+            shift_id = row.shift_id
+            shift_dept_id = row.dept_id
+            shift_dept_name = db_dept.get_dept_name_by_id(db, row.dept_id)
+
+            onduty_user = db_user.get_nick_name_by_id(db, row.primary_staff_id)
+            onduty_leader = db_user.get_nick_name_by_id(db, row.leader_id)
+            video_url = "#"
+            call_url = "#"
+
+            # 避免同一个部门重复
+            if shift_dept_id in dept_list:
+                continue
+
+            dept_list.append(shift_dept_id)
+            new_detail = OnlineRollCallDetail(
+                pid = new_call_id,
+                shift_id = shift_id,
+                dept_id = shift_dept_id,
+                dept_name = shift_dept_name,
+                onduty_user = onduty_user,
+                onduty_leader = onduty_leader,
+                video_url = video_url,
+                call_url = call_url,
+                ack_status = 0,
+                act_time = None,
+                create_time = datetime.now(),
+                del_flag = '0',
+                ack_type = 0
+            )
+            db.add(new_detail)
+            db.commit()
+
+        return {
+            "code": 200,
+            "msg": "点名创建成功",
+            "data": new_call_id
+        }
+
+    except AppException as e:
+        return {
+            "code": e.code,
+            "msg": e.msg
+        }
+
+    except Exception as e:
+        traceback.print_exc()
+        # 处理异常
+        raise HTTPException(status_code=500, detail=str(e))
+    
+
+# 一键点名全市至镇街
+@router.post("/create_by_city_to_district")
+async def create_by_city_to_district(
+    db: Session = Depends(get_db),
+    user_id = Depends(valid_access_token)
+):
+    current_date = datetime.now().date()
+    current_time  = datetime.now().time()
+    try:
+        # 过滤当前时间内的值班人员
+        q = db.query(DutyShift).filter(func.char_length(DutyShift.area_code) <= 9)
+        q = q.filter(DutyShift.shift_date == current_date)
+        q = q.filter(DutyShift.shfit_status == 0)
+        q = q.filter(DutyShift.start_time < current_time).filter(DutyShift.end_time > current_time)
+        rows = q.all()
+        
+        user_count = len(rows)
+        if user_count == 0:
+            raise AppException(500, "暂无相关值班人员信息")
+
+        new_call = OnlineRollCallBase(
+            call_type = 1,
+            recorded_by = user_id,
+            create_time = datetime.now(),
+            del_flag = '0',
+            call_status = 1,
+            user_count = user_count,
+            ack_count = 0,
+            unack_count = user_count,
+            remark = '',
+            update_time = datetime.now()
+        )
+        db.add(new_call)
+        db.commit()
+        db.refresh(new_call)
+        new_call_id = new_call.id
+
+        dept_list = []
+        for row in rows:
+            shift_id = row.shift_id
+            shift_dept_id = row.dept_id
+            shift_dept_name = db_dept.get_dept_name_by_id(db, row.dept_id)
+
+            onduty_user = db_user.get_nick_name_by_id(db, row.primary_staff_id)
+            onduty_leader = db_user.get_nick_name_by_id(db, row.leader_id)
+            video_url = "#"
+            call_url = "#"
+
+            # 避免同一个部门重复
+            if shift_dept_id in dept_list:
+                continue
 
-        user_row = db.query(SysUser).filter(SysUser.user_id == user_id).first()
-        user_name = user_row.user_name
-        nick_name = user_row.nick_name
-        dept_id = user_row.dept_id
+            dept_list.append(shift_dept_id)
+            new_detail = OnlineRollCallDetail(
+                pid = new_call_id,
+                shift_id = shift_id,
+                dept_id = shift_dept_id,
+                dept_name = shift_dept_name,
+                onduty_user = onduty_user,
+                onduty_leader = onduty_leader,
+                video_url = video_url,
+                call_url = call_url,
+                ack_status = 0,
+                act_time = None,
+                create_time = datetime.now(),
+                del_flag = '0',
+                ack_type = 0
+            )
+            db.add(new_detail)
+            db.commit()
 
-        dept_row = db.query(SysDept).filter(SysDept.dept_id == dept_id).first()
-        dept_name = dept_row.dept_name
+        return {
+            "code": 200,
+            "msg": "点名创建成功",
+            "data": new_call_id
+        }
+
+    except AppException as e:
+        return {
+            "code": e.code,
+            "msg": e.msg
+        }
 
+    except Exception as e:
+        traceback.print_exc()
+        # 处理异常
+        raise HTTPException(status_code=500, detail=str(e))
+
+
+# 新建点名(分区/县点名)
+@router.post("/create_by_dept_ids")
+async def create_by_dept_ids(
+    db: Session = Depends(get_db),
+    body = Depends(remove_xss_json),
+    user_id = Depends(valid_access_token)
+):
+    current_date = datetime.now().date()
+    current_time  = datetime.now().time()
+    try:
+        if len(body['depts']) == 0:
+            raise AppException(500, "请勾选部门")
+        
         new_call = OnlineRollCallBase(
-            call_type = body['call_type'],
+            call_type = 3,
             recorded_by = user_id,
-            create_time = datetime.now,
+            create_time = datetime.now(),
             del_flag = '0',
             call_status = 1,
-            user_count = body['user_count'],
+            user_count = 0,
             ack_count = 0,
             unack_count = 0,
             remark = body['remark'],
@@ -59,30 +294,31 @@ async def create_all(
         db.refresh(new_call)
         new_call_id = new_call.id
 
-        for u in body['users']:
-            call_user_id = u['user_id']
-            call_dept_id = 0
-            call_nick_name = ''
-            call_dept_name = ''
-            user_row = db.query(SysUser).filter(SysUser.user_id == call_user_id).first()
-            if user_row is not None:
-                call_nick_name = user_row.nick_name
-                call_dept_row = db.query(SysDept).filter(SysDept.dept_id == user_row.dept_id).first()
-                call_dept_id = call_dept_row.dept_id
-                call_dept_name = call_dept_row.dept_name
-
-                # 关联值班班获取值班人员信息
-                onduty_user = "-1"
-                onduty_leader = "-1"
-                video_url = "..."
-                call_url = "..."
+        for dept_id in body['depts']:
+            # 过滤当前时间内的值班人员
+            q = db.query(DutyShift).filter(DutyShift.dept_id == dept_id)
+            q = q.filter(DutyShift.shift_date == current_date)
+            q = q.filter(DutyShift.shfit_status == 0)
+            q = q.filter(DutyShift.start_time < current_time).filter(DutyShift.end_time > current_time)
+            row = q.first()
+            
+            if row is not None:
+                print(dept_id)
+            
+                shift_id = row.shift_id
+                shift_dept_id = row.dept_id
+                shift_dept_name = db_dept.get_dept_name_by_id(db, row.dept_id)
 
+                onduty_user = db_user.get_nick_name_by_id(db, row.primary_staff_id)
+                onduty_leader = db_user.get_nick_name_by_id(db, row.leader_id)
+                video_url = "#"
+                call_url = "#"
+                
                 new_detail = OnlineRollCallDetail(
                     pid = new_call_id,
-                    user_id = call_user_id,
-                    dept_id = call_dept_id,
-                    nick_name = call_nick_name,
-                    dept_name = call_dept_name,
+                    shift_id = shift_id,
+                    dept_id = shift_dept_id,
+                    dept_name = shift_dept_name,
                     onduty_user = onduty_user,
                     onduty_leader = onduty_leader,
                     video_url = video_url,
@@ -95,20 +331,36 @@ async def create_all(
                 )
                 db.add(new_detail)
                 db.commit()
-            else:
-                raise Exception("用户不存在")
+
+        # 检查多次,避免人员为空
+        user_count = db.query(OnlineRollCallDetail).filter(OnlineRollCallDetail.pid == new_call_id).count()
+        if user_count == 0:
+            db.query(OnlineRollCallBase).filter(OnlineRollCallBase.id == new_call_id).delete()
+            db.commit()
+
+            raise AppException(500, "暂无相关值班人员信息")
+        
+        db.query(OnlineRollCallBase).filter(OnlineRollCallBase.id == new_call_id).update({"user_count": user_count, "unack_count": user_count})
+        db.commit()
 
         return {
             "code": 200,
             "msg": "点名创建成功",
             "data": new_call_id
         }
+    
+    except AppException as e:
+        return {
+            "code": e.code,
+            "msg": e.msg
+        }
 
     except Exception as e:
         traceback.print_exc()
         # 处理异常
         raise HTTPException(status_code=500, detail=str(e))
     
+
 # 结束应答
 @router.post("/end")
 async def end_call(
@@ -226,18 +478,26 @@ async def get_event_detail(
             }
         
         data = get_model_dict(base_row)
-        data['create_time'] = get_datetime_str(data['create_time'])
+        data['begin_time'] = get_datetime_str(data['create_time'])
         data['update_time'] = get_datetime_str(data['update_time'])
+        data['duration_time'] = ''
+
+        # 已结束
+        if data['call_status'] == 2:
+            time_diff = base_row.end_time - base_row.create_time
+            # hours,minutes,seconds = str(time_diff).split(':')
+            data['duration_time'] = str(time_diff)
     
         detail_rows = db.query(OnlineRollCallDetail).filter(OnlineRollCallDetail.pid == call_id).all()
-        users = []
+        items = []
         for row in detail_rows:
             detail_info = get_model_dict(row)
-            detail_info['create_time'] = get_datetime_str(detail_info['create_time'])
+            detail_info['begin_time'] = get_datetime_str(detail_info['create_time'])
             detail_info['act_time'] = get_datetime_str(detail_info['act_time'])
-            users.append(detail_info)
+            detail_info['ack_status_text'] = get_ack_status_text(detail_info['ack_status'])
+            items.append(detail_info)
 
-        data['users'] = users
+        data['items'] = items
 
         return {
             "code": 200,
@@ -248,4 +508,81 @@ async def get_event_detail(
     except Exception as e:
         # 处理异常
         traceback.print_exc()
-        raise HTTPException(status_code=500, detail=str(e))
+        raise HTTPException(status_code=500, detail=str(e))
+    
+
+def get_ack_status_text(act_status: int) -> str:
+    if act_status == 0:
+        return '未应答'
+    elif act_status == 1:
+        return '已接通'
+    elif act_status == 2:
+        return '呼叫中'
+    else:
+        return str(act_status)
+    
+#应答详情
+@router.get('/list')
+async def get_event_list(
+    request: Request,
+    begin_date: str = Query('', description='开始时间'),
+    end_date: str = Query('', description='结束时间'), 
+    page: int = Query(1, gt=0, description='页码'),
+    page_size: int = Query(10, gt=0, description='pageSize'),
+    db: Session = Depends(get_db)):
+
+    try:
+        where = and_(OnlineRollCallBase.del_flag == '0')
+
+        if begin_date is not None and begin_date != '':
+            begin_date = datetime.strptime(begin_date, "%Y-%m-%d")
+            where = and_(where, OnlineRollCallBase.create_time > begin_date)
+
+        if end_date is not None and end_date != '':
+            end_date = datetime.strptime(end_date, "%Y-%m-%d") + timedelta(days=1)
+            where = and_(where, OnlineRollCallBase.create_time < end_date)
+
+        print(where)
+        
+        # 计算总条目数
+        q = db.query(func.count(OnlineRollCallBase.id))
+        q = q.filter(where)
+        total = q.scalar()
+        
+        # 执行分页查询
+        q = db.query(OnlineRollCallBase)
+        q = q.filter(where)
+        rows = q.order_by(OnlineRollCallBase.id.desc()).offset((page - 1) * page_size).limit(page_size).all()
+        data = []
+
+        for row in rows:
+            duration_time = ""
+            # 已结束
+            if row.call_status == 2:
+                time_diff = row.end_time - row.create_time
+                # hours,minutes,seconds = str(time_diff).split(':')
+                duration_time = str(time_diff)
+                
+            data.append({
+                "id": row.id,
+                "begin_time": get_datetime_str(row.create_time),
+                "end_time": get_datetime_str(row.end_time),
+                "duration_time": duration_time,
+                "call_status": row.call_status,
+                "ack_count": row.ack_count,
+                "unack_count": row.unack_count
+            })
+
+        # 返回结果
+        return {
+            "code": 200,
+            "msg": "查询成功",
+            "data": data,
+            "total": total
+        }
+
+    except Exception as e:
+        # 处理异常
+        traceback.print_exc()
+        raise HTTPException(status_code=500, detail=str(e))
+    

+ 2 - 0
utils/__init__.py

@@ -56,6 +56,8 @@ def from_timestamp2(timestamp: int):
         return dt
 
 def get_datetime_str(val: datetime) -> str:
+    if val is None:
+        return ''
     return val.strftime("%Y-%m-%d %H:%M:%S")