From e65399d3738355c1adf9771d055ab406a0d4d166 Mon Sep 17 00:00:00 2001 From: xueyinfei <1207092115@qq.com> Date: Thu, 27 Feb 2025 14:56:23 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B5=81=E7=A8=8B=E9=85=8D=E7=BD=AE=E6=A8=A1?= =?UTF-8?q?=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/approval_controller.py | 20 ++++- .../module_admin/dao/approval_dao.py | 27 +++++- .../module_admin/entity/do/approval_do.py | 14 +++ .../module_admin/entity/vo/approval_vo.py | 21 +++++ .../module_admin/service/approval_service.py | 17 +++- .../module_admin/service/user_service.py | 40 +++++---- vue-fastapi-frontend/src/api/flow/flow.js | 24 +++-- .../src/views/system/flow/conf.vue | 87 ++++++++++++------- .../src/views/system/flow/index.vue | 2 +- 9 files changed, 190 insertions(+), 62 deletions(-) diff --git a/vue-fastapi-backend/module_admin/controller/approval_controller.py b/vue-fastapi-backend/module_admin/controller/approval_controller.py index cc22957..939f970 100644 --- a/vue-fastapi-backend/module_admin/controller/approval_controller.py +++ b/vue-fastapi-backend/module_admin/controller/approval_controller.py @@ -5,7 +5,7 @@ from fastapi import APIRouter, Depends, Request, UploadFile, File, Form from sqlalchemy.ext.asyncio import AsyncSession from config.get_db import get_db from module_admin.entity.vo.user_vo import CurrentUserModel -from module_admin.entity.vo.approval_vo import ApplyModel, OperateModel, ApprovalQueryObject +from module_admin.entity.vo.approval_vo import ApplyModel, OperateModel, ApprovalQueryObject, SaveConfModel from module_admin.service.login_service import LoginService from module_admin.service.approval_service import ApprovalService from utils.log_util import logger @@ -55,3 +55,21 @@ async def cancel_apply(request: Request, current_user: CurrentUserModel = Depends(LoginService.get_current_user)): operate_result = await ApprovalService.cancel_apply_services(query_db, flow_id, current_user) return ResponseUtil.success(msg=operate_result.message) + + +@approvalController.get("/conf/list") +async def get_conf_list(request: Request, + module: str, + query_db: AsyncSession = Depends(get_db), + current_user: CurrentUserModel = Depends(LoginService.get_current_user)): + meta_query_result = await ApprovalService.get_conf_list_services(module, query_db, current_user) + return ResponseUtil.success(data=meta_query_result) + + +@approvalController.post("/conf/save") +async def save_flow_config( + saveConfModel: SaveConfModel, + query_db: AsyncSession = Depends(get_db), +): + operate_result = await ApprovalService.save_flow_config_services(query_db, saveConfModel) + return ResponseUtil.success(msg=operate_result.message) diff --git a/vue-fastapi-backend/module_admin/dao/approval_dao.py b/vue-fastapi-backend/module_admin/dao/approval_dao.py index b74cd70..0b174ff 100644 --- a/vue-fastapi-backend/module_admin/dao/approval_dao.py +++ b/vue-fastapi-backend/module_admin/dao/approval_dao.py @@ -1,6 +1,6 @@ from sqlalchemy import desc, delete, func, select, update from sqlalchemy.ext.asyncio import AsyncSession -from module_admin.entity.do.approval_do import FlowApproval +from module_admin.entity.do.approval_do import FlowApproval, FlowConfig from module_admin.entity.vo.approval_vo import ApprovalQueryObject from module_admin.entity.vo.user_vo import CurrentUserModel from sqlalchemy import select, text, cast, Integer, and_, or_, outerjoin, func, join @@ -76,3 +76,28 @@ class ApprovalDao: .first() ) return result + + @classmethod + async def get_conf_list(cls, db: AsyncSession, module: str): + result = ( + ( + await db.execute(select(FlowConfig).where( + FlowConfig.module == module + )) + ).scalars().all() + ) + return result + + @classmethod + async def add_flow_config(cls, db: AsyncSession, conf: dict): + db_conf = FlowConfig(**conf) + db.add(db_conf) + await db.flush() + return conf + + @classmethod + async def delete_flow_by_module(cls, module: str, db: AsyncSession): + await db.execute(delete(FlowConfig).where(FlowConfig.module == module)) + + + 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 c9a273b..fe5d613 100644 --- a/vue-fastapi-backend/module_admin/entity/do/approval_do.py +++ b/vue-fastapi-backend/module_admin/entity/do/approval_do.py @@ -18,3 +18,17 @@ class FlowApproval(Base): nextStep = Column(Integer, default=None, comment="下一步编号") status = Column(String(10), default=None, comment='状态') approvalFlow = Column(Text, default=None, comment='审批流') # [{审批人:‘’,审批时间:‘’,'审批结果':‘’,审批意见:''},{}]数组 + + +class FlowConfig(Base): + __tablename__ = 'flow_config' + + id = Column(String(50), primary_key=True, comment='id') + code = Column(String(50), default='', comment='节点代码') + text = Column(String(255), default='', comment='节点名称') + type = Column(String(50), default=None, comment='节点类型,Role/User') + module = Column(String(50), default=None, comment='所属模块') + step = Column(Integer, default=None, comment='步骤') + x = Column(Integer, default=None, comment='节点位置x') + y = Column(Integer, default=None, comment='节点位置y') + parent = Column(Text, default=None, comment="父节点") 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 1fcce05..8cbca6a 100644 --- a/vue-fastapi-backend/module_admin/entity/vo/approval_vo.py +++ b/vue-fastapi-backend/module_admin/entity/vo/approval_vo.py @@ -32,3 +32,24 @@ class EditObjectModel(BaseModel): approver: Optional[str] = None nextStep: Optional[int] = None approvalFlow: Optional[str] = None + + +class FlowConfModel(BaseModel): + id: Optional[str] + code: Optional[str] + text: Optional[str] + type: Optional[str] + module: Optional[str] + step: Optional[int] + x: Optional[int] + y: Optional[int] + parent: Optional[str] + + +class SaveConfModel(BaseModel): + module: Optional[str] + confList: Optional[List[Union[FlowConfModel, None]]] + + + + diff --git a/vue-fastapi-backend/module_admin/service/approval_service.py b/vue-fastapi-backend/module_admin/service/approval_service.py index 1235c5e..5c38733 100644 --- a/vue-fastapi-backend/module_admin/service/approval_service.py +++ b/vue-fastapi-backend/module_admin/service/approval_service.py @@ -4,7 +4,7 @@ import uuid from typing import Optional from sqlalchemy.ext.asyncio import AsyncSession from module_admin.entity.vo.common_vo import CrudResponseModel -from module_admin.entity.vo.approval_vo import ApplyModel, OperateModel, ApprovalQueryObject, EditObjectModel +from module_admin.entity.vo.approval_vo import ApplyModel, OperateModel, ApprovalQueryObject, EditObjectModel, SaveConfModel from module_admin.entity.vo.user_vo import CurrentUserModel from module_admin.entity.do.approval_do import FlowApproval from exceptions.exception import ServiceException, ServiceWarning @@ -119,3 +119,18 @@ class ApprovalService: flow.status = 'canceled' await ApprovalDao.edit_flow_approval(query_db, flow) return CrudResponseModel(is_success=True, message='操作成功') + + @classmethod + async def get_conf_list_services(cls, module: str, query_db: AsyncSession, current_user: CurrentUserModel): + result = await ApprovalDao.get_conf_list(query_db, module) + return result + + @classmethod + async def save_flow_config_services(cls, query_db: AsyncSession, saveConfModel: SaveConfModel): + await ApprovalDao.delete_flow_by_module(saveConfModel.module, query_db) + for item in saveConfModel.confList: + confDict = item.model_dump(exclude_unset=True) + await ApprovalDao.add_flow_config(query_db, confDict) + await query_db.commit() + return CrudResponseModel(is_success=True, message='操作成功') + diff --git a/vue-fastapi-backend/module_admin/service/user_service.py b/vue-fastapi-backend/module_admin/service/user_service.py index 415fc58..f31b073 100644 --- a/vue-fastapi-backend/module_admin/service/user_service.py +++ b/vue-fastapi-backend/module_admin/service/user_service.py @@ -212,11 +212,14 @@ class UserService: :return: 编辑用户校验结果 """ edit_user = page_object.model_dump(exclude_unset=True, exclude={'admin'}) + requestDs = True if page_object.type != 'status' and page_object.type != 'avatar' and page_object.type != 'pwd': del edit_user['role_ids'] del edit_user['post_ids'] del edit_user['role'] if page_object.type == 'status' or page_object.type == 'avatar' or page_object.type == 'pwd': + if page_object.type == 'status' or page_object.type == 'avatar': + requestDs = False del edit_user['type'] user_info = await cls.user_detail_services(query_db, edit_user.get('user_id')) if user_info.data and user_info.data.user_id: @@ -228,24 +231,25 @@ class UserService: elif page_object.email and not await cls.check_email_unique_services(query_db, page_object): raise ServiceException(message=f'修改用户{page_object.user_name}失败,邮箱账号已存在') try: - payload = { - 'id': -1, - 'userName': user_info.data.user_name, - 'userPassword': page_object.password if page_object.password else '', - 'email': page_object.email if page_object.email else '', - 'phone': page_object.phonenumber if page_object.phonenumber else '', - 'tenantId': -1, - 'state': 1 if (page_object.status is None or page_object.status == '0') else 0 - } - headers = {'dashUserName': currentUserName, 'dashPassword': currentPassword} - response_post = requests.post(url=AppConfig.ds_server_url+'/dolphinscheduler/users/update', - params=payload, - headers=headers, verify=False) - if response_post.status_code != 200: - if response_post.status_code != 201: - raise Exception("服务异常,请确保各节点是否在线") - if not response_post.json().get('success'): - raise Exception(response_post.json().get('msg')) + if requestDs: + payload = { + 'id': -1, + 'userName': user_info.data.user_name, + 'userPassword': page_object.password if page_object.password else '', + 'email': page_object.email if page_object.email else '', + 'phone': page_object.phonenumber if page_object.phonenumber else '', + 'tenantId': -1, + 'state': 1 if (page_object.status is None or page_object.status == '0') else 0 + } + headers = {'dashUserName': currentUserName, 'dashPassword': currentPassword} + response_post = requests.post(url=AppConfig.ds_server_url+'/dolphinscheduler/users/update', + params=payload, + headers=headers, verify=False) + if response_post.status_code != 200: + if response_post.status_code != 201: + raise Exception("服务异常,请确保各节点是否在线") + if not response_post.json().get('success'): + raise Exception(response_post.json().get('msg')) await UserDao.edit_user_dao(query_db, edit_user) if page_object.type != 'status' and page_object.type != 'avatar' and page_object.type != 'pwd': await UserDao.delete_user_role_dao(query_db, UserRoleModel(userId=page_object.user_id)) diff --git a/vue-fastapi-frontend/src/api/flow/flow.js b/vue-fastapi-frontend/src/api/flow/flow.js index 77bb46c..52c7ee9 100644 --- a/vue-fastapi-frontend/src/api/flow/flow.js +++ b/vue-fastapi-frontend/src/api/flow/flow.js @@ -9,14 +9,6 @@ export function getApprovalList(data) { }) } -export function getflowList(data) { - return request({ - url: '/default-api/approval/list', - method: 'get', - params: {module:data} - }) -} - export function getWaitingFlowCount() { return request({ url: '/default-api/approval/waitingTotal', @@ -30,4 +22,20 @@ export function operateProcess(data) { method: 'post', data: data }) +} + +export function getFlowConfList(data) { + return request({ + url: '/default-api/approval/conf/list', + method: 'get', + params: {module:data} + }) +} + +export function saveFlowConfig(data){ + return request({ + url: '/default-api/approval/conf/save', + method: 'post', + data: data + }) } \ No newline at end of file diff --git a/vue-fastapi-frontend/src/views/system/flow/conf.vue b/vue-fastapi-frontend/src/views/system/flow/conf.vue index 79a4585..6ef7a5f 100644 --- a/vue-fastapi-frontend/src/views/system/flow/conf.vue +++ b/vue-fastapi-frontend/src/views/system/flow/conf.vue @@ -8,14 +8,9 @@ 保存 -
- - 元数据信息模块 - -
-
- - 其他模块----敬请期待 +
+ + {{ item.text }}
@@ -64,13 +59,14 @@ import { Selection } from '@antv/x6-plugin-selection' import { Clipboard } from '@antv/x6-plugin-clipboard' import { ref, nextTick, computed, watch, reactive, onMounted } from 'vue' import { listRole } from "@/api/system/role"; -import {getflowList } from "@/api/flow/flow"; - +import {getFlowConfList,saveFlowConfig } from "@/api/flow/flow"; +const { proxy } = getCurrentInstance(); +const moduleList = ref([{'module':'metaDataInfo','text':'元数据'},{'module':'other','text':'其他模块(敬请期待)'}]) let graph = null const roleList = ref([]) const data = ref([]) -const checked = ref('元数据') +const checked = ref('metaDataInfo') const ports = ref({ groups: { top: { @@ -230,7 +226,7 @@ function register(){ inherit: 'edge', attrs: { line: { - stroke: '#A2B1C3', + stroke: '#C71E1EFF', strokeWidth: 2, }, }, @@ -239,14 +235,19 @@ function register(){ ) } function changeBackGround(module){ - if (module === '元数据信息'){ - checked.value = '元数据' - } - if (module === '其他模块'){ - checked.value = '其他模块' - } - getflowList(checked.value).then(res=>{ - + checked.value = module + searchFlowData() +} +function searchFlowData(){ + getFlowConfList(checked.value).then(res=>{ + let resData = res.data + if (resData.length > 0){ + for (let i = 0; i < resData.length; i++) { + resData[i].parent = JSON.parse(resData[i].parent) + } + } + data.value = resData + loadGraphData() }) } function showAddDialog(){ @@ -258,7 +259,6 @@ function showAddDialog(){ function save(){ let json = graph.toJSON() let array = json.cells; - console.log(array) let flows = [] if (array.length>0){ for (let i = 0; i < array.length; i++) { @@ -268,6 +268,7 @@ function save(){ id: cell.id, code: cell.code, text: cell.attrs.text.text, + module: checked.value, type: cell.type, x: cell.position.x, y: cell.position.y, @@ -292,7 +293,36 @@ function save(){ } } } - console.log(flows) + if (flows.length>0){ + for (let i = 0; i < flows.length; i++) { + flows[i].step = getNodeStep(flows[i],flows) + } + for (let i = 0; i < flows.length; i++) { + flows[i].parent = JSON.stringify(flows[i].parent) + } + let saveData = { + module: checked.value, + confList: flows + } + saveFlowConfig(saveData).then(res=>{ + proxy.$modal.msgSuccess("操作成功"); + }) + } +} +function getNodeStep(node,array){ + if(node.parent.length === 0){ + return 1; + }else { + let step = 0; + node.parent.forEach(parentId=>{ + let parentNode = array.find(item => item.id === parentId) + let parentStep = getNodeStep(parentNode,array) + if (step < (parentStep +1)){ + step = parentStep + 1; + } + }) + return step + } } function loadGraphData(){ let array = [] @@ -302,6 +332,7 @@ function loadGraphData(){ code: item.code, attrs: {text:{text: item.text}}, position:{x:item.x,y:item.y}, + type: item.type, width: 100, height: 60, shape: "activity" @@ -333,16 +364,8 @@ onMounted(re=>{ grid:true, autoResize: true, connecting: { - router: 'orth', + router: 'manhattan' }, - createEdge() { - return new Shape.Edge({ - "id": uuid(), - "shape": "bpmn-edge", - "source": "7", - "target": "13" - }); - } }) graph.use(new Keyboard()) .use( @@ -375,7 +398,7 @@ onMounted(re=>{ const ports = container.querySelectorAll('.x6-port-body',) showPorts(ports, false) }) - loadGraphData() + searchFlowData() }) diff --git a/vue-fastapi-frontend/src/views/system/flow/index.vue b/vue-fastapi-frontend/src/views/system/flow/index.vue index afc9886..eace342 100644 --- a/vue-fastapi-frontend/src/views/system/flow/index.vue +++ b/vue-fastapi-frontend/src/views/system/flow/index.vue @@ -74,7 +74,7 @@