diff --git a/vue-fastapi-backend/module_admin/dao/approval_dao.py b/vue-fastapi-backend/module_admin/dao/approval_dao.py index 0b174ff..71ffb23 100644 --- a/vue-fastapi-backend/module_admin/dao/approval_dao.py +++ b/vue-fastapi-backend/module_admin/dao/approval_dao.py @@ -39,15 +39,27 @@ class ApprovalDao: @classmethod async def get_flow_list(cls, db: AsyncSession, query_param: ApprovalQueryObject, current_user: CurrentUserModel): + roleList = current_user.roles + query = (select(FlowApproval).where( + (FlowApproval.applicant == query_param.applicant) if query_param.applicant else True, + (FlowApproval.businessType == query_param.businessType) if query_param.businessType else True, + or_(*[FlowApproval.nextStepRole.like(f'%{role}%') for role in roleList], + FlowApproval.nextStepUser.like(f'%{current_user.user.user_name}%')), + ).order_by(FlowApproval.applyTime) + .distinct()) + # 注意:这里不执行查询,而是将查询对象传递给 paginate 方法 + result = await PageUtil.paginate(db, query, query_param.page_num, query_param.page_size, True) + return result + + @classmethod + async def get_owner_flow_list(cls, db: AsyncSession, query_param: ApprovalQueryObject, + current_user: CurrentUserModel): query = ( select(FlowApproval) .where( - (FlowApproval.applicant == query_param.status) if query_param.applicant else True, + (FlowApproval.applicant == query_param.applicant) if query_param.applicant else True, (FlowApproval.businessType == query_param.businessType) if query_param.businessType else True, - or_( - FlowApproval.approver == current_user.user.user_name, - FlowApproval.approver.in_(current_user.roles) - ) if current_user.user.user_name != 'admin' else True + FlowApproval.approvalFlow.like(f'%{current_user.user.user_name}%') ) .order_by(FlowApproval.applyTime) .distinct() @@ -57,9 +69,16 @@ class ApprovalDao: return result @classmethod - async def get_waiting_total(cls, db: AsyncSession, current_user: CurrentUserModel): - return (await db.execute(select(func.count()).select_from(FlowApproval) - .where(FlowApproval.approver == current_user.user.user_name))).scalar() + async def get_all_waitingOrPendingFlows(cls, db: AsyncSession): + result = ( + ( + await db.execute(select(FlowApproval).where( + or_(FlowApproval.status == 'waiting', + FlowApproval.status == 'pending') + )) + ).scalars().all() + ) + return result @classmethod async def get_flow_by_idAndUser(cls, db: AsyncSession, flow_id: str, username: str): @@ -99,5 +118,26 @@ class ApprovalDao: async def delete_flow_by_module(cls, module: str, db: AsyncSession): await db.execute(delete(FlowConfig).where(FlowConfig.module == module)) + @classmethod + async def get_nextstep_conf(cls, module: str, db: AsyncSession, step: int): + result = ( + ( + await db.execute(select(FlowConfig).where( + FlowConfig.module == module, + FlowConfig.step == step + )) + ).scalars().all() + ) + return result - + @classmethod + async def get_first_node_conf(cls, module: str, db: AsyncSession): + result = ( + ( + await db.execute(select(FlowConfig).where( + FlowConfig.module == module, + FlowConfig.step == 1 + )) + ).scalars().all() + ) + return result diff --git a/vue-fastapi-backend/module_admin/entity/do/approval_do.py b/vue-fastapi-backend/module_admin/entity/do/approval_do.py index fe5d613..30af726 100644 --- a/vue-fastapi-backend/module_admin/entity/do/approval_do.py +++ b/vue-fastapi-backend/module_admin/entity/do/approval_do.py @@ -14,10 +14,12 @@ class FlowApproval(Base): businessId = Column(String(255), default='', comment='业务id串') applicant = Column(String(50), default=None, comment='申请人') applyTime = Column(String(50), default=None, comment='审批时间') - approver = Column(String(50), default=None, comment='下一步审批人') - nextStep = Column(Integer, default=None, comment="下一步编号") + currentFlowId = Column(String(50), default=None, comment='当前审批节点id') + nextStep = Column(String(255), default=None, comment="下一步编号") + nextStepRole = Column(String(255), default=None, comment="下一步审批角色") + nextStepUser = Column(String(255), default=None, comment="下一步审批人") status = Column(String(10), default=None, comment='状态') - approvalFlow = Column(Text, default=None, comment='审批流') # [{审批人:‘’,审批时间:‘’,'审批结果':‘’,审批意见:''},{}]数组 + approvalFlow = Column(Text, default=None, comment='审批流') # [{审批人:‘’,审批节点id:‘’,审批时间:‘’,'审批结果':‘’,审批意见:''},{}]数组 class FlowConfig(Base): diff --git a/vue-fastapi-backend/module_admin/entity/vo/approval_vo.py b/vue-fastapi-backend/module_admin/entity/vo/approval_vo.py index 8cbca6a..38e39fd 100644 --- a/vue-fastapi-backend/module_admin/entity/vo/approval_vo.py +++ b/vue-fastapi-backend/module_admin/entity/vo/approval_vo.py @@ -24,13 +24,16 @@ class ApprovalQueryObject(BaseModel): page_size: int applicant: Optional[str] = None businessType: Optional[str] = None + status: Optional[str] = None class EditObjectModel(BaseModel): id: Optional[str] = None status: Optional[str] = None - approver: Optional[str] = None + currentNodeId: Optional[str] = None nextStep: Optional[int] = None + nextStepRole: Optional[str] = None + nextStepUser: Optional[str] = None approvalFlow: Optional[str] = None diff --git a/vue-fastapi-backend/module_admin/service/approval_service.py b/vue-fastapi-backend/module_admin/service/approval_service.py index 5c38733..c492eba 100644 --- a/vue-fastapi-backend/module_admin/service/approval_service.py +++ b/vue-fastapi-backend/module_admin/service/approval_service.py @@ -11,6 +11,7 @@ from exceptions.exception import ServiceException, ServiceWarning from datetime import datetime from utils.common_util import CamelCaseUtil from module_admin.dao.approval_dao import ApprovalDao +from module_admin.dao.user_dao import UserDao from module_admin.dao.meta_dao import MetaDao @@ -20,7 +21,7 @@ class ApprovalService: """ @classmethod - async def apply_services(cls, result_db: AsyncSession, apply: ApplyModel): + async def apply_services(cls, result_db: AsyncSession, apply: ApplyModel, module: str): flow_approval = FlowApproval() flow_approval.id = uuid.uuid4() flow_approval.businessType = apply.businessType @@ -28,9 +29,10 @@ class ApprovalService: flow_approval.applicant = apply.applicant flow_approval.applyTime = datetime.now().strftime("%Y-%m-%d %H:%M:%S") flow_approval.status = 'waiting' - # todo 后期进行流程配置,角色 or 人员 下一步审批人 - flow_approval.approver = 'admin' - flow_approval.nextStep = '1' + listConf = await ApprovalDao.get_first_node_conf(module, result_db) + flow_approval.nextStep = json.dumps([item.id for item in listConf]) + flow_approval.nextStepRole = json.dumps([item.code for item in listConf if item.type == 'Role']) + flow_approval.nextStepUser = json.dumps([item.code for item in listConf if item.type == 'User']) await ApprovalDao.add_flow_approval(result_db, flow_approval) await result_db.commit() return CrudResponseModel(is_success=True, message='申请成功') @@ -44,28 +46,49 @@ class ApprovalService: raise ServiceException(message='所操作的流程已结束') if flow_approval.status == 'canceled': raise ServiceException(message='所操作的流程已撤回') + edit = EditObjectModel() + edit.id = flow_approval.id + flowConfList = await ApprovalDao.get_conf_list(result_db, flow_approval.businessType) + nextSteps = json.loads(flow_approval.nextStep) + nextStepFlowList = [item for item in flowConfList if item.id in nextSteps] + nextFlowList = [item for item in nextStepFlowList if item.code in current_user.roles] + confNodeId = nextFlowList[0].id array = [] if flow_approval.approvalFlow is not None: array = json.loads(flow_approval.approvalFlow) + if operate.operateType == 'success': + nextFlow = [] + for flowConf in flowConfList: + parent = json.loads(flowConf.parent) + if confNodeId in parent: + nextFlow.append(flowConf) + if len(nextFlow) > 0: + edit.status = 'pending' # 有下一步执行人,则设置为 pending + edit.nextStep = json.dumps([item.id for item in nextFlow]) + edit.nextStepRole = json.dumps([item.code for item in nextFlow if item.type == 'Role']) + edit.nextStepUser = json.dumps([item.code for item in nextFlow if item.type == 'User']) + edit.currentNodeId = confNodeId + else: + edit.status = 'succeed' + edit.currentNodeId = confNodeId + edit.nextStep = '[]' + edit.nextStepRole = '[]' + edit.nextStepUser = '[]' + if operate.operateType == 'reject': + edit.status = 'rejected' + edit.currentNodeId = confNodeId + edit.nextStep = '[]' + edit.nextStepRole = '[]' + edit.nextStepUser = '[]' array.append({'operator': current_user.user.user_name, + 'confFlowId': confNodeId, 'operateTime': datetime.now().strftime("%Y-%m-%d %H:%M:%S"), 'operate': operate.operateType, 'operateComment': operate.operateComment, }) - edit = EditObjectModel() - edit.id = flow_approval.id edit.approvalFlow = json.dumps(array) - if operate.operateType == 'success': - # todo 增加流程配置,并查询出下一步操作人以及步骤 - edit.status = 'succeed' # 有下一步执行人,则设置为 pending - edit.approver = None - edit.nextStep = -1 - if operate.operateType == 'reject': - edit.status = 'rejected' - edit.approver = None - edit.nextStep = -1 - if flow_approval.businessType == 't_metadata_supp_info': - await cls.syncSuppInfo(result_db, flow_approval.businessId, operate.operateType) + if flow_approval.businessType == 'metaDataInfo': + await cls.syncSuppInfo(result_db, flow_approval.businessId, edit.status) await ApprovalDao.edit_flow_approval(result_db, edit.model_dump(exclude_unset=True)) await result_db.commit() return CrudResponseModel(is_success=True, message='操作成功') @@ -98,13 +121,37 @@ class ApprovalService: @classmethod async def get_flow_list_services(cls, query_db: AsyncSession, query_param: ApprovalQueryObject, current_user: CurrentUserModel): - result = await ApprovalDao.get_flow_list(query_db, query_param, current_user) - return result + if query_param.status == 'waiting': + result = await ApprovalDao.get_flow_list(query_db, query_param, current_user) + return result + if query_param.status == 'over': + result = await ApprovalDao.get_owner_flow_list(query_db, query_param, current_user) + return result + return None @classmethod async def get_waiting_total_services(cls, query_db: AsyncSession, current_user: CurrentUserModel): - result = await ApprovalDao.get_waiting_total(query_db, current_user) - return result + approval_list = await ApprovalDao.get_all_waitingOrPendingFlows(query_db) + count = 0 + for item in approval_list: + nextRoles = json.loads(item.nextStepRole) + nextUsers = json.loads(item.nextStepUser) + if len(nextRoles)>0 and len(nextUsers) > 0: + if current_user.user.user_name in nextUsers: + count = count+1 + break + if any(element in set(current_user.roles) for element in nextRoles): + count = count+1 + break + if len(nextRoles) > 0 and len(nextUsers) == 0: + if any(element in set(current_user.roles) for element in nextRoles): + count = count+1 + break + if len(nextRoles) == 0 and len(nextUsers) > 0: + if current_user.user.user_name in nextUsers: + count = count+1 + break + return count @classmethod async def cancel_apply_services(cls, query_db: AsyncSession, flow_id: str, diff --git a/vue-fastapi-backend/module_admin/service/meta_service.py b/vue-fastapi-backend/module_admin/service/meta_service.py index db5df8d..906e70a 100644 --- a/vue-fastapi-backend/module_admin/service/meta_service.py +++ b/vue-fastapi-backend/module_admin/service/meta_service.py @@ -99,10 +99,10 @@ class MetaService: await MetaDao.insertMetadataFldSuppInfoVett(suppColumnInfo, result_db) await result_db.commit() applyModel = ApplyModel() - applyModel.businessType = "t_metadata_supp_info" + applyModel.businessType = "metaDataInfo" applyModel.businessId = tableOnum applyModel.applicant = current_user.user.user_name - await ApprovalService.apply_services(result_db, applyModel) + await ApprovalService.apply_services(result_db, applyModel, 'metaDataInfo') return CrudResponseModel(is_success=True, message='操作成功') @classmethod diff --git a/vue-fastapi-frontend/public/checkbox-circle-line.png b/vue-fastapi-frontend/public/checkbox-circle-line.png new file mode 100644 index 0000000..a1ec9b2 Binary files /dev/null and b/vue-fastapi-frontend/public/checkbox-circle-line.png differ diff --git a/vue-fastapi-frontend/public/close-circle-line.png b/vue-fastapi-frontend/public/close-circle-line.png new file mode 100644 index 0000000..797de58 Binary files /dev/null and b/vue-fastapi-frontend/public/close-circle-line.png differ diff --git a/vue-fastapi-frontend/public/x6-user.png b/vue-fastapi-frontend/public/x6-user.png new file mode 100644 index 0000000..c5f380f Binary files /dev/null and b/vue-fastapi-frontend/public/x6-user.png differ diff --git a/vue-fastapi-frontend/src/views/meta/metaInfo/index.vue b/vue-fastapi-frontend/src/views/meta/metaInfo/index.vue index d1868fd..e3dcc93 100644 --- a/vue-fastapi-frontend/src/views/meta/metaInfo/index.vue +++ b/vue-fastapi-frontend/src/views/meta/metaInfo/index.vue @@ -81,16 +81,16 @@ 重置 - - - 导出 - - + + + + + + + + + + @@ -135,7 +135,7 @@