diff --git a/vue-fastapi-backend/module_admin/controller/meta_controller.py b/vue-fastapi-backend/module_admin/controller/meta_controller.py index e6e27a5..6f8909f 100644 --- a/vue-fastapi-backend/module_admin/controller/meta_controller.py +++ b/vue-fastapi-backend/module_admin/controller/meta_controller.py @@ -1,12 +1,14 @@ -from fastapi import APIRouter, Depends, Request +from fastapi import APIRouter, Depends, Request, UploadFile, File 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.service.login_service import LoginService from utils.response_util import ResponseUtil +from utils.common_util import bytes2file_response from module_admin.service.meta_service import MetaService -from module_admin.entity.vo.meta_vo import MetaPageObject, MetaColObject, SuppleModel, MetaBusinessRelShipObject, MetaProcQueryObject +from module_admin.entity.vo.meta_vo import MetaPageObject, MetaColObject, SuppleModel, MetaBusinessRelShipObject, \ + MetaProcQueryObject metaController = APIRouter(prefix='/dasset', dependencies=[Depends(LoginService.get_current_user)]) @@ -67,8 +69,8 @@ async def getBusinessRelationShip(request: Request, @metaController.get("/meta/business/proc") async def getBusinessProc(request: Request, - meta_query: MetaProcQueryObject = Depends(MetaProcQueryObject.as_query), - query_db: AsyncSession = Depends(get_db)): + meta_query: MetaProcQueryObject = Depends(MetaProcQueryObject.as_query), + query_db: AsyncSession = Depends(get_db)): result = await MetaService.getMetaProc(query_db, meta_query) return ResponseUtil.success(data=result) @@ -79,3 +81,19 @@ async def getBloodRelationShip(request: Request, query_db: AsyncSession = Depends(get_db)): result = await MetaService.getBloodRelationShip(query_db, procId) return ResponseUtil.success(data=result) + + +@metaController.post("/meta/importTemplate") +async def export_system_user_template(request: Request, query_db: AsyncSession = Depends(get_db)): + meta_import_template_result = await MetaService.get_meta_import_template_services() + return ResponseUtil.streaming(data=bytes2file_response(meta_import_template_result)) + + +@metaController.post('/meta/importData') +async def batch_import_meta_data( + request: Request, + file: UploadFile = File(...), + query_db: AsyncSession = Depends(get_db), + current_user: CurrentUserModel = Depends(LoginService.get_current_user)): + batch_import_result = await MetaService.batch_import_meta_services(query_db, file, current_user) + return ResponseUtil.success(msg=batch_import_result) diff --git a/vue-fastapi-backend/module_admin/dao/datastd_dao.py b/vue-fastapi-backend/module_admin/dao/datastd_dao.py index 6b9d6a0..ec491d8 100644 --- a/vue-fastapi-backend/module_admin/dao/datastd_dao.py +++ b/vue-fastapi-backend/module_admin/dao/datastd_dao.py @@ -590,6 +590,18 @@ class DataStdDao: ).scalars().first() return List + @classmethod + async def get_data_dict_by_code(cls, db: AsyncSession, code: str): + List = ( + await db.execute( + select(DataStdDict) + .where( + DataStdDict.data_dict_no == code + ) + ) + ).scalars().first() + return List + @classmethod async def get_data_sec_lvl_by_dict_id(cls, db: AsyncSession, id: str): List = ( diff --git a/vue-fastapi-backend/module_admin/dao/meta_dao.py b/vue-fastapi-backend/module_admin/dao/meta_dao.py index d7e3717..147bead 100644 --- a/vue-fastapi-backend/module_admin/dao/meta_dao.py +++ b/vue-fastapi-backend/module_admin/dao/meta_dao.py @@ -291,7 +291,18 @@ class MetaDao: return query_result @classmethod - async def get_supp_column_vett_by_tableInfo(cls, db: AsyncSession, tableInfo: MetadataSuppInfoVett): + async def get_supp_table_vett_by_businessId(cls, businessId: str, db: AsyncSession): + query_result = ( + ( + await db.execute( + select(MetadataSuppInfoVett).where(MetadataSuppInfoVett.business_id == businessId).distinct() + ) + ).scalars().all() + ) + return query_result + + @classmethod + async def get_supp_column_vett_by_tableInfo(cls, db: AsyncSession, tableInfo): query_result = ( ( await db.execute( @@ -302,10 +313,10 @@ class MetaDao: MetadataFldSuppInfoVett.data_dict_id == DataStdDict.onum, # 假设关联条件 isouter=True, # 可选,是否左连接 ).where( - MetadataFldSuppInfoVett.ssys_id == tableInfo.ssys_id, - MetadataFldSuppInfoVett.mdl_name == tableInfo.mdl_name, - MetadataFldSuppInfoVett.tab_eng_name == tableInfo.tab_eng_name, - MetadataFldSuppInfoVett.apply_time == tableInfo.apply_time + MetadataFldSuppInfoVett.ssys_id == tableInfo['ssysId'], + MetadataFldSuppInfoVett.mdl_name == tableInfo['mdlName'], + MetadataFldSuppInfoVett.tab_eng_name == tableInfo['tabEngName'], + MetadataFldSuppInfoVett.apply_time == tableInfo['applyTime'] ) ) ).all() diff --git a/vue-fastapi-backend/module_admin/entity/do/meta_do.py b/vue-fastapi-backend/module_admin/entity/do/meta_do.py index d867c37..714cb93 100644 --- a/vue-fastapi-backend/module_admin/entity/do/meta_do.py +++ b/vue-fastapi-backend/module_admin/entity/do/meta_do.py @@ -68,6 +68,7 @@ class MetadataSuppInfoVett(Base): apply_time = Column(String(255, collation='utf8_general_ci'), comment='申请时间') apply_status = Column(String(255, collation='utf8_general_ci'), comment='申请状态') upd_time = Column(String(255, collation='utf8_general_ci'), comment='更新时间') + business_id = Column(String(255, collation='utf8_general_ci'), comment='审批业务相关ID') oldTableData = Column(Text, comment='修改前表格数据') @@ -161,6 +162,7 @@ class MetadataFldSuppInfoVett(Base): rec_subm_prsn = Column(String(255, collation='utf8_general_ci'), comment='记录提交人') apply_time = Column(String(255, collation='utf8_general_ci'), comment='申请时间') apply_status = Column(String(255, collation='utf8_general_ci'), comment='申请状态') + business_id = Column(String(255, collation='utf8_general_ci'), comment='审批业务相关ID') oldColumnData = Column(Text, comment='修改前字段信息') diff --git a/vue-fastapi-backend/module_admin/service/approval_service.py b/vue-fastapi-backend/module_admin/service/approval_service.py index 7c2925a..2286a5f 100644 --- a/vue-fastapi-backend/module_admin/service/approval_service.py +++ b/vue-fastapi-backend/module_admin/service/approval_service.py @@ -112,32 +112,33 @@ class ApprovalService: return CrudResponseModel(is_success=True, message='操作成功') @classmethod - async def syncSuppInfo(cls, result_db: AsyncSession, suppId: str, operateType: str): - table = await MetaDao.get_supp_table_vett_by_id(suppId, result_db) - if table is None: + async def syncSuppInfo(cls, result_db: AsyncSession, businessId: str, operateType: str): + tableList = await MetaDao.get_supp_table_vett_by_businessId(businessId, result_db) + if tableList is None or len(tableList) == 0: raise ServiceException(message='所查询的业务数据不存在') - if table.apply_status == 'succeed' or table.apply_status == 'rejected': + if tableList[0].apply_status == 'succeed' or tableList[0].apply_status == 'rejected': raise ServiceException(message='所改业务已审核完毕') - if table.apply_status == 'canceled': + if tableList[0].apply_status == 'canceled': raise ServiceException(message='所改业务已撤销申请') - column_list = await MetaDao.get_meta_col_supp_vett(table, result_db) - if column_list is not None and len(column_list) > 0: - for column in column_list: - column.apply_status = operateType - suppColumn = await MetaDao.get_supp_column_by_vett(column, result_db) - await MetaDao.updateMetadataFldSuppInfoVett(column.onum, operateType, result_db) - if operateType != 'canceled': - if suppColumn is None: - await MetaDao.insertMetadataFldSuppInfo(column, result_db) - else: - await MetaDao.updateMetadataFldSuppInfo(suppColumn.onum, column, result_db) - suppTable = await MetaDao.get_supp_table_by_vett(table.ssys_id, table.mdl_name, table.tab_eng_name, result_db) - await MetaDao.updateMetadataSuppInfoVett(table.onum, operateType, result_db) - if operateType != 'canceled': - if suppTable is None: - await MetaDao.insertMetadataSuppInfo(table, result_db) - else: - await MetaDao.updateMetadataSuppInfo(suppTable.onum, table, result_db) + for table in tableList: + column_list = await MetaDao.get_meta_col_supp_vett(table, result_db) + if column_list is not None and len(column_list) > 0: + for column in column_list: + column.apply_status = operateType + suppColumn = await MetaDao.get_supp_column_by_vett(column, result_db) + await MetaDao.updateMetadataFldSuppInfoVett(column.onum, operateType, result_db) + if operateType != 'canceled': + if suppColumn is None: + await MetaDao.insertMetadataFldSuppInfo(column, result_db) + else: + await MetaDao.updateMetadataFldSuppInfo(suppColumn.onum, column, result_db) + suppTable = await MetaDao.get_supp_table_by_vett(table.ssys_id, table.mdl_name, table.tab_eng_name, result_db) + await MetaDao.updateMetadataSuppInfoVett(table.onum, operateType, result_db) + if operateType != 'canceled': + if suppTable is None: + await MetaDao.insertMetadataSuppInfo(table, result_db) + else: + await MetaDao.updateMetadataSuppInfo(suppTable.onum, table, result_db) return CrudResponseModel(is_success=True, message='操作成功') @classmethod diff --git a/vue-fastapi-backend/module_admin/service/meta_service.py b/vue-fastapi-backend/module_admin/service/meta_service.py index 5c02006..a331468 100644 --- a/vue-fastapi-backend/module_admin/service/meta_service.py +++ b/vue-fastapi-backend/module_admin/service/meta_service.py @@ -1,6 +1,9 @@ +import io import json import uuid +import pandas as pd +from fastapi import UploadFile from module_admin.entity.vo.meta_vo import MetaPageObject, MetaColObject, SuppleModel, MetaBusinessRelShipObject, \ MetaProcQueryObject from module_admin.entity.do.meta_do import MetadataSuppInfo, MetadataFldSuppInfo, MetadataSuppInfoVett, \ @@ -21,6 +24,8 @@ from module_admin.service.approval_service import ApprovalService from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.user_vo import CurrentUserModel from utils.common_util import CamelCaseUtil +from config.env import AppConfig +import requests class MetaService: @@ -81,6 +86,7 @@ class MetaService: oldTable = await MetaDao.get_supp_table_by_vett(supple.ssys_id, supple.mdl_name, supple.tab_eng_name, result_db) tableInfo = await MetaDao.get_meta_table(supple.ssys_id, supple.mdl_name, supple.tab_eng_name, result_db) tableOnum = uuid.uuid4() + businessId = uuid.uuid4() if hasTable is not None: if hasTable.apply_status == 'waiting': raise ServiceException(message=f'所补录对象已存在补录待审核记录,请等待审批完成或撤回申请后,再行补录') @@ -99,6 +105,7 @@ class MetaService: suppTableInfo.tab_clas = supple.tab_clas suppTableInfo.rec_subm_prsn = current_user.user.user_name suppTableInfo.apply_time = applyTime + suppTableInfo.business_id = businessId suppTableInfo.apply_status = 'waiting' suppTableInfo.oldTableData = cls.castToTableStr(oldTable, tableInfo) await MetaDao.insertMetadataSuppInfoVett(suppTableInfo, result_db) @@ -135,7 +142,7 @@ class MetaService: await MetaDao.insertMetadataFldSuppInfoVett(suppColumnInfo, result_db) applyModel = ApplyModel() applyModel.businessType = "metaDataInfo" - applyModel.businessId = tableOnum + applyModel.businessId = businessId applyModel.applicant = current_user.user.user_name await ApprovalService.apply_services(result_db, applyModel, 'metaDataInfo') await result_db.commit() @@ -193,22 +200,20 @@ class MetaService: @classmethod async def get_meta_apply_detail_services(cls, result_db: AsyncSession, businessId: str): - tableData = await MetaDao.get_supp_table_vett_by_id(businessId, result_db) - table = CamelCaseUtil.transform_result(tableData) - clas_list = await MetaDao.get_meta_tab_clas(result_db, tableData.ssys_id, tableData.mdl_name, - tableData.tab_eng_name) - table['batchTabClas'] = CamelCaseUtil.transform_result(clas_list) - columnData = await MetaDao.get_supp_column_vett_by_tableInfo(result_db, tableData) - column_list = CamelCaseUtil.transform_result(columnData) - for column in column_list: - col_list = await MetaDao.get_meta_fld_clas(result_db, column['ssysId'], column['mdlName'], - column['tabEngName'], column['fldEngName']) - column['batchColClas'] = CamelCaseUtil.transform_result(col_list) - result = dict( - table=table, - column=column_list - ) - return result + tableDataList = await MetaDao.get_supp_table_vett_by_businessId(businessId, result_db) + tableList = CamelCaseUtil.transform_result(tableDataList) + for tableData in tableList: + clas_list = await MetaDao.get_meta_tab_clas(result_db, tableData['ssysId'], tableData['mdlName'], + tableData['tabEngName']) + tableData['batchTabClas'] = CamelCaseUtil.transform_result(clas_list) + columnData = await MetaDao.get_supp_column_vett_by_tableInfo(result_db, tableData) + column_list = CamelCaseUtil.transform_result(columnData) + for column in column_list: + col_list = await MetaDao.get_meta_fld_clas(result_db, column['ssysId'], column['mdlName'], + column['tabEngName'], column['fldEngName']) + column['batchColClas'] = CamelCaseUtil.transform_result(col_list) + tableData['columnList'] = column_list + return tableList @classmethod async def get_table_by_id(cls, result_db: AsyncSession, tableId: int): @@ -513,3 +518,234 @@ class MetaService: "tableList": tableList } return result + + @staticmethod + async def get_meta_import_template_services(): + """ + 获取元数据导入模板service + :return: 元数据导入模板excel的二进制数据 + """ + table_header_list = ['系统代码', '模式名称', '对象英文名', '补录对象名称', '补录对象描述', '负责人'] + column_header_list = ['系统代码', '模式名称', '对象英文名', '字段英文名', '字段补录名', '补录主键', + '补录字段描述', '引用字典/标准', '安全等级', '负责人'] + selector_header_list = ['补录主键', '安全等级'] + option_list = [{}, {'补录主键': ['是', '否'], '安全等级': ['S1', 'S2', 'S3', 'S4']}] + sheet_config1 = dict( + sheet_name="表信息", header_list=table_header_list, selector_header_list=[] + ) + sheet_config2 = dict( + sheet_name="字段信息", header_list=column_header_list, selector_header_list=selector_header_list + ) + sheet_configs = [sheet_config1, sheet_config2] + binary_data = get_excel_template_with_sheets( + sheet_configs, # 每个Sheet的配置(包含表头、选择器等) + option_list + ) + + return binary_data + + @classmethod + async def batch_import_meta_services(cls, + result_db: AsyncSession, + file: UploadFile, + current_user: CurrentUserModel): + import_err_msg = [] + # 调用DS接口通过系统代码查询系统ID + url = f'{AppConfig.ds_server_url}/dolphinscheduler/datasources?pageNo=1&pageSize=100' + headers = {'dashUserName': current_user.user.user_name, 'dashPassword': current_user.user.password} + response = requests.get(url, headers=headers, verify=False) + dataSourceList = [] + if response.reason == 'OK': + response_text = response.text + data = json.loads(response_text) + dataSourceList = data["data"]["totalList"] + else: + raise ServiceException(message=f'系统异常,获取数据源失败') + skip_table = [] + businessId = uuid.uuid4() + applyTime = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + table_header_dict = { + '系统代码': 'ssys_cd', + '模式名称': 'mdl_name', + '对象英文名': 'tab_eng_name', + '补录对象名称': 'tab_crrct_name', + '补录对象描述': 'tab_desc', + '负责人': 'rec_subm_prsn' + } + column_header_dict = { + '系统代码': 'ssys_cd', + '模式名称': 'mdl_name', + '对象英文名': 'tab_eng_name', + '字段英文名': 'fld_eng_name', + '字段补录名': 'fld_crrct_name', + '补录主键': 'crrct_pk_flag', + '补录字段描述': 'fld_desc', + '引用字典/标准': 'data_dict_id', + '安全等级': 'data_sec_lvl', + '负责人': 'rec_subm_prsn' + } + contents = await file.read() + excel_file = pd.ExcelFile(io.BytesIO(contents)) + await file.close() + # 获取所有sheet名称 + sheet_names = excel_file.sheet_names + # 逐个读取 + tableSheet = sheet_names[0] + columnSheet = sheet_names[1] + successCount = 0 + # 校验, 1、各必填内容不能为空, 2.系统代码映射的系统是否存在 3.表是否存在 4.字段是否存在5.引用的字典标准是否存在6.标准的系统与表系统是否对应 + if tableSheet == '表信息': + # 表信息补录 + df = excel_file.parse(sheet_name=tableSheet) + df.rename(columns=table_header_dict, inplace=True) + for index, row in df.iterrows(): + noneValid = '' + if row['ssys_cd'] is None or len(row['ssys_cd']) == 0: + noneValid += "sheet[表信息]中行:" + str(index+1) + "中的系统代码不能为空" + if row['mdl_name'] is None or len(row['mdl_name']) == 0: + if len(noneValid) > 0: + noneValid += ",模式名称不能为空" + else: + noneValid += "sheet[表信息]中行:" + str(index+1) + "中的模式名称不能为空" + if row['tab_eng_name'] is None or len(row['tab_eng_name']) == 0: + if len(noneValid) > 0: + noneValid += ",表英文名称不能为空" + else: + noneValid += "sheet[表信息]中行:" + str(index+1) + "中的表英文名不能为空" + if len(noneValid) > 0: + import_err_msg.append(noneValid) + continue + ssysId = next((item["id"] for item in dataSourceList if item["name"] == row['ssys_cd']), None) + if ssysId is None: + import_err_msg.append("行:" + str(index+1) + "中的系统不存在,需重新修正") + continue + hasTable = await MetaDao.get_lastest_meta_data_supp_vett(result_db, ssysId, row['mdl_name'], + row['tab_eng_name']) + if hasTable: + if hasTable.apply_status == 'waiting': + import_err_msg.append( + 'sheet[表信息]中行:' + str(index+1) + ' 导入的系统代码:' + row['ssys_cd'] + ',模式名称:' + row['mdl_name'] + + ',对象英文名:' + row['tab_eng_name'] + + '已存在补录待审核记录,请等待审批完成或撤回申请后,再行导入') + if hasTable.apply_status == 'pending': + import_err_msg.append( + 'sheet[字段信息]中行:' + str(index+1) + ' 导入的系统代码:' + row['ssys_cd'] + ',模式名称:' + row['mdl_name'] + + ',对象英文名:' + row['tab_eng_name'] + + '已存在待审核记录,请等待审批完成或撤回申请后,再行导入') + skip_table.append({'ssys_id': ssysId, 'mdl_name': row['mdl_name'], + 'tab_eng_name': row['tab_eng_name']}) + continue + oldTable = await MetaDao.get_supp_table_by_vett(ssysId, row['mdl_name'], + row['tab_eng_name'], result_db) + tableInfo = await MetaDao.get_meta_table(ssysId, row['mdl_name'], + row['tab_eng_name'], result_db) + if tableInfo is None: + import_err_msg.append("sheet[表信息]中行:"+str(index+1) + "中所对应的表不存在,无法上传补录") + continue + tableOnum = uuid.uuid4() + suppTableInfo = MetadataSuppInfoVett() + suppTableInfo.onum = tableOnum + suppTableInfo.ssys_id = ssysId + suppTableInfo.mdl_name = row['mdl_name'] + suppTableInfo.tab_eng_name = row['tab_eng_name'] + suppTableInfo.tab_crrct_name = row['tab_crrct_name'] + suppTableInfo.tab_desc = row['tab_desc'] + suppTableInfo.pic = oldTable.pic if oldTable else None + suppTableInfo.gov_flag = oldTable.gov_flag if oldTable else None + suppTableInfo.tab_clas = oldTable.tab_clas if oldTable else None + suppTableInfo.rec_subm_prsn = row['rec_subm_prsn'] + suppTableInfo.apply_time = applyTime + suppTableInfo.apply_status = 'waiting' + suppTableInfo.business_id = businessId + suppTableInfo.oldTableData = cls.castToTableStr(oldTable, tableInfo) + await MetaDao.insertMetadataSuppInfoVett(suppTableInfo, result_db) + successCount += 1 + if columnSheet == '字段信息': + # 字段信息补录 + df = excel_file.parse(sheet_name=columnSheet) + df.rename(columns=column_header_dict, inplace=True) + for index, row in df.iterrows(): + noneValid = '' + if row['ssys_cd'] is None or len(row['ssys_cd']) == 0: + noneValid += "sheet[字段信息]中行:" + str(index+1) + "中的系统代码不能为空" + if row['mdl_name'] is None or len(row['mdl_name']) == 0: + if len(noneValid) > 0: + noneValid += ",模式名称不能为空" + else: + noneValid += "sheet[字段信息]中行:" + str(index+1) + "中的模式名称不能为空" + if row['tab_eng_name'] is None or len(row['tab_eng_name']) == 0: + if len(noneValid) > 0: + noneValid += ",表英文名称不能为空" + else: + noneValid += "sheet[字段信息]中行:" + str(index+1) + "中的表英文名不能为空" + if len(noneValid) > 0: + import_err_msg.append(noneValid) + continue + ssysId = next((item["id"] for item in dataSourceList if item["name"] == row['ssys_cd']), None) + if any( + table['ssys_id'] == ssysId + and table['mdl_name'] == row['mdl_name'] + and table['tab_eng_name'] == row['tab_eng_name'] + for table in skip_table + ): + continue + oldColumn = await MetaDao.get_supp_column_by_columnInfo(ssysId, row['mdl_name'], + row['tab_eng_name'], + row['fld_eng_name'], result_db) + data_dict_name = '' + if oldColumn and oldColumn.data_dict_id and oldColumn.data_dict_id != '': + oldDict = await DataStdDao.get_data_dict_by_id(result_db, oldColumn.data_dict_id) + data_dict_name = oldDict.data_dict_cn_name if oldDict else '' + columnInfo = await MetaDao.get_meta_column(ssysId, row['mdl_name'], + row['tab_eng_name'], + row['fld_eng_name'], result_db) + if columnInfo is None: + import_err_msg.append("sheet[字段信息]中行:"+str(index+1) + "中所对应的字段不存在,无法上传补录") + continue + dataDictId = '' + if row['data_dict_id'] and len(row['data_dict_id']) > 0: + dataDict = await DataStdDao.get_data_dict_by_code(result_db, row['data_dict_id']) + if dataDict is None: + import_err_msg.append("sheet[字段信息]中行:"+str(index+1) + "中所对应的数据字典不存在,无法上传补录") + continue + else: + if int(dataDict.src_sys) != ssysId: + import_err_msg.append("sheet[字段信息]中行:"+str(index+1) + "中所对应的数据字典所属系统与表所属系统不一致,无法上传补录") + continue + else: + dataDictId = dataDict.onum + suppColumnInfo = MetadataFldSuppInfoVett() + suppColumnInfo.onum = uuid.uuid4() + suppColumnInfo.ssys_id = ssysId + suppColumnInfo.mdl_name = row['mdl_name'] + suppColumnInfo.tab_eng_name = row['tab_eng_name'] + suppColumnInfo.fld_eng_name = row['fld_eng_name'] + suppColumnInfo.fld_crrct_name = row['fld_crrct_name'] + suppColumnInfo.crrct_pk_flag = True if row['crrct_pk_flag'] and row['crrct_pk_flag'] == '是' else False + suppColumnInfo.fld_desc = row['fld_desc'] + suppColumnInfo.pic = oldColumn.pic if oldColumn else None + suppColumnInfo.fld_clas = oldColumn.fld_clas if oldColumn else None + suppColumnInfo.fld_null_rate = oldColumn.fld_null_rate if oldColumn else None + suppColumnInfo.data_dict_id = dataDictId if dataDictId != '' else None + suppColumnInfo.data_sec_lvl = row['data_sec_lvl'] + suppColumnInfo.rec_stat = oldColumn.rec_stat if oldColumn else None + suppColumnInfo.rec_subm_prsn = row['rec_subm_prsn'] + suppColumnInfo.business_id = businessId + suppColumnInfo.apply_time = applyTime + suppColumnInfo.apply_status = 'waiting' + suppColumnInfo.oldColumnData = cls.castToColumnStr(oldColumn, columnInfo, data_dict_name) + await MetaDao.insertMetadataFldSuppInfoVett(suppColumnInfo, result_db) + successCount += 1 + if successCount > 0: + applyModel = ApplyModel() + applyModel.businessType = "metaDataInfo" + applyModel.businessId = businessId + applyModel.applicant = current_user.user.user_name + await ApprovalService.apply_services(result_db, applyModel, 'metaDataInfo') + await result_db.commit() + else: + import_err_msg.append("上传的数据均有问题,本次导入0条") + if len(import_err_msg) > 0: + return ";".join(import_err_msg) + else: + return "操作成功" diff --git a/vue-fastapi-frontend/src/views/meta/metaInfo/index.vue b/vue-fastapi-frontend/src/views/meta/metaInfo/index.vue index cc901be..aba3b8a 100644 --- a/vue-fastapi-frontend/src/views/meta/metaInfo/index.vue +++ b/vue-fastapi-frontend/src/views/meta/metaInfo/index.vue @@ -98,6 +98,14 @@ @click="runBloodAnalysisTask" >执行血缘解析任务 + + 导入 + - + @@ -741,7 +749,45 @@ - + + + +
将文件拖到此处,或点击上传
+ +
+ +
+ + + + @@ -755,6 +801,7 @@ import BusinssRelation from "./businssRelation.vue"; import BloodRelation from "./bloodRelation.vue"; import {listMetadataSecOptions} from "@/api/metadataConfig/metadataConfig.js"; + import {getToken} from "@/utils/auth.js"; const data = reactive({ queryParams:{ @@ -842,6 +889,21 @@ }); const stddictOptions = ref([]) const secLvlOptions = ref([]) + /*** 导入参数 */ + const upload = reactive({ + // 是否显示弹出层(导入) + open: false, + // 弹出层标题(导入) + title: "", + // 是否禁用上传 + isUploading: false, + // 设置上传的请求头部 + headers: { Authorization: "Bearer " + getToken() }, + // 上传的地址 + url: import.meta.env.VITE_APP_BASE_API + "/dasset/meta/importData", + showResult: false, + resultMsg: [] + }); function changeColumnTab(){ if (activeColumnTab.value === 'businessRelation'){ @@ -876,7 +938,7 @@ } function generateDemoData(){ let param ={ - dataAstSrc: currentMetaData.value.ssysId, + dataAstSrc: currentMetaData.value.ssysCd, dataAstEngName:currentMetaData.value.mdlName+"."+currentMetaData.value.tabEngName } getMetaSecurityData(param).then(res=>{ @@ -1458,7 +1520,11 @@ proxy.$modal.msgSuccess(response.data); } function confirmPublish(){ - publishAstData({assetItems:dataAstList.value}).then(res=>{ + let data = dataAstList.value + data.forEach(dataAst =>{ + delete dataAst.showDataAstSrc + }) + publishAstData({assetItems:data}).then(res=>{ proxy.$modal.msgSuccess(res.msg) astPublish.value = false }) @@ -1482,9 +1548,38 @@ getMetaClasList().then(res=>{ metaClasList.value = res.data }) - - } + function openUploadMetaInfoDialog(){ + upload.title = "数据导入"; + upload.open = true; + } + /**文件上传中处理 */ + const handleFileUploadProgress = (event, file, fileList) => { + upload.isUploading = true; + } + /** 提交上传文件 */ + function submitFileForm() { + proxy.$refs["uploadRef"].submit(); + } + /** 下载模板操作 */ + function importTemplate() { + proxy.download("/dasset/meta/importTemplate", { + }, `meta_template_${new Date().getTime()}.xlsx`); + } + /** 文件上传成功处理 */ + const handleFileSuccess = (response, file, fileList) => { + upload.open = false; + upload.isUploading = false; + proxy.$refs["uploadRef"].handleRemove(file); + if (response.msg === '操作成功'){ + proxy.$modal.msgSuccess(response.msg) + }else { + upload.showResult = true + upload.resultMsg = response.msg.split(";") + } + getList(); + } + function applyDataAst(){ if(selectedRows.value.length === 0){ proxy.$modal.msgWarning("请至少选择一条元数据进行发布") @@ -1498,6 +1593,7 @@ dataAstStat: '1', dataAstDesc:'', dataAstSrc: row.ssysId, + showDataAstSrc: row.ssysCd, astNo: row.extractOnum, dataAstClas: JSON.stringify(row.batchTabClas), showTabClas: row.showTabClas, @@ -1511,7 +1607,7 @@ const filterNode = (value, data) => { if (!value) return true; return data.name.indexOf(value) !== -1; - }; + } function handleNodeClick(data) { queryParams.value.ssysId = data.id; handleQuery(); diff --git a/vue-fastapi-frontend/src/views/system/flow/index.vue b/vue-fastapi-frontend/src/views/system/flow/index.vue index 6c9c481..9ed1541 100644 --- a/vue-fastapi-frontend/src/views/system/flow/index.vue +++ b/vue-fastapi-frontend/src/views/system/flow/index.vue @@ -539,8 +539,67 @@
+ + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -589,7 +648,9 @@ const data = reactive({ }); const showFlowDialog = ref(false); const businessDialog = ref(false); +const metaDataListDialog = ref(false); const oldTableInfo = ref([]); +const metaDataList = ref([]); const oldColumnList = ref([]); const newTableInfo = ref([]); const newColumnList = ref([]); @@ -604,6 +665,13 @@ function getList() { total.value = res.data.total }) } +const getSrcSysName = (id) => { + const match = dsSysList.find(item => item.id === id); + return match ? match.name : id; +}; +function handleViewMetadata(row) { + transformMetaDetailData(row) +} function register(){ Graph.registerNode( 'activity', @@ -853,155 +921,162 @@ function resetQuery(){ } getList() } -function showBusinessDataDialog(row){ - - if (row.businessType === 'metaDataInfo'){ - businessDialog.value = true - let param = { - businessId: row.businessId - } - getMetaInfoApplyBusinessDetail(param).then(res=>{ - let data = JSON.parse(JSON.stringify(res.data)) - let table = JSON.parse(data.table.oldTableData) - let batchTabClas = data.table.batchTabClas - let showOldTabClas = [] - if (batchTabClas && batchTabClas.length>0){ - showOldTabClas = JSON.parse(JSON.stringify(batchTabClas)) - if (table.tabClas && table.tabClas !== '[]' && table.tabClas !== 'null'){ - let oldTabClas = JSON.parse(table.tabClas) - for (let i = 0; i < oldTabClas.length; i++) { - for (let j = 0; j < showOldTabClas.length; j++) { - if (showOldTabClas[j].clasPriClas === oldTabClas[i].clasPriClas - && showOldTabClas[j].clasScdClas === oldTabClas[i].clasScdClas - && showOldTabClas[j].clasThreClas === oldTabClas[i].clasThreClas - && showOldTabClas[j].clasName === oldTabClas[i].clasName - ){ - showOldTabClas[j] = oldTabClas[i] - } - } +function transformMetaDetailData(data){ + let table = JSON.parse(data.oldTableData) + let batchTabClas = data.batchTabClas + let showOldTabClas = [] + if (batchTabClas && batchTabClas.length>0){ + showOldTabClas = JSON.parse(JSON.stringify(batchTabClas)) + if (table.tabClas && table.tabClas !== '[]' && table.tabClas !== 'null'){ + let oldTabClas = JSON.parse(table.tabClas) + for (let i = 0; i < oldTabClas.length; i++) { + for (let j = 0; j < showOldTabClas.length; j++) { + if (showOldTabClas[j].clasPriClas === oldTabClas[i].clasPriClas + && showOldTabClas[j].clasScdClas === oldTabClas[i].clasScdClas + && showOldTabClas[j].clasThreClas === oldTabClas[i].clasThreClas + && showOldTabClas[j].clasName === oldTabClas[i].clasName + ){ + showOldTabClas[j] = oldTabClas[i] } } - }else { - showOldTabClas = JSON.parse(table.tabClas) } - table.showTabClas = showOldTabClas - oldTableInfo.value = JSON.parse(JSON.stringify(table)) - oldTableInfo.value.ssysCd = dsSysList.find(item => item.id === oldTableInfo.value.ssysId)?.name - newTableInfo.value = { - applyStatus:data.table.applyStatus, - applyTime:data.table.applyTime, - crrctVerNum:data.table.crrctVerNum, - govFlag:data.table.govFlag, - mdlName:data.table.mdlName, - onum:data.table.onum, - pic:data.table.pic, - recStat:data.table.recStat, - recSubmPrsn:data.table.recSubmPrsn, - ssysCd:dsSysList.find(item => item.id === data.table.ssysId)?.name, - tabClas:data.table.tabClas, - tabCrrctName:data.table.tabCrrctName, - tabDesc:data.table.tabDesc, - tabEngName:data.table.tabEngName, - updTime:data.table.updTime, - tabCnName:table.tabCnName, - tabRecNum:table.tabRecNum, - tabType:table.tabType, + } + }else { + showOldTabClas = JSON.parse(table.tabClas) + } + table.showTabClas = showOldTabClas + oldTableInfo.value = JSON.parse(JSON.stringify(table)) + oldTableInfo.value.ssysCd = dsSysList.find(item => item.id === oldTableInfo.value.ssysId)?.name + newTableInfo.value = { + applyStatus:data.applyStatus, + applyTime:data.applyTime, + crrctVerNum:data.crrctVerNum, + govFlag:data.govFlag, + mdlName:data.mdlName, + onum:data.onum, + pic:data.pic, + recStat:data.recStat, + recSubmPrsn:data.recSubmPrsn, + ssysCd:dsSysList.find(item => item.id === data.ssysId)?.name, + tabClas:data.tabClas, + tabCrrctName:data.tabCrrctName, + tabDesc:data.tabDesc, + tabEngName:data.tabEngName, + updTime:data.updTime, + tabCnName:table.tabCnName, + tabRecNum:table.tabRecNum, + tabType:table.tabType, + } + let showNewTabClas = [] + if (batchTabClas && batchTabClas.length>0){ + showNewTabClas = JSON.parse(JSON.stringify(batchTabClas)) + if (newTableInfo.value.tabClas && newTableInfo.value.tabClas !== '[]' && newTableInfo.value.tabClas !== 'null'){ + let newTabClas = JSON.parse(newTableInfo.value.tabClas) + for (let i = 0; i < newTabClas.length; i++) { + for (let j = 0; j < showNewTabClas.length; j++) { + if (showNewTabClas[j].clasPriClas === newTabClas[i].clasPriClas + && showNewTabClas[j].clasScdClas === newTabClas[i].clasScdClas + && showNewTabClas[j].clasThreClas === newTabClas[i].clasThreClas + && showNewTabClas[j].clasName === newTabClas[i].clasName + ){ + showNewTabClas[j] = newTabClas[i] + } + } } - let showNewTabClas = [] - if (batchTabClas && batchTabClas.length>0){ - showNewTabClas = JSON.parse(JSON.stringify(batchTabClas)) - if (newTableInfo.value.tabClas && newTableInfo.value.tabClas !== '[]' && newTableInfo.value.tabClas !== 'null'){ - let newTabClas = JSON.parse(newTableInfo.value.tabClas) - for (let i = 0; i < newTabClas.length; i++) { - for (let j = 0; j < showNewTabClas.length; j++) { - if (showNewTabClas[j].clasPriClas === newTabClas[i].clasPriClas - && showNewTabClas[j].clasScdClas === newTabClas[i].clasScdClas - && showNewTabClas[j].clasThreClas === newTabClas[i].clasThreClas - && showNewTabClas[j].clasName === newTabClas[i].clasName + } + }else { + showNewTabClas = JSON.parse(data.tabClas) + } + newTableInfo.value.showTabClas = showNewTabClas + newColumnList.value = [] + oldColumnList.value = [] + if (data.columnList && data.columnList.length > 0){ + for (let i = 0; i < data.columnList.length; i++) { + let col = data.columnList[i] + let column = JSON.parse(col.oldColumnData) + let batchColClas = col.batchColClas + let showOldColClas = [] + if (batchColClas && batchColClas.length>0){ + showOldColClas = JSON.parse(JSON.stringify(batchColClas)) + if (column.fldClas && column.fldClas !== '[]' && column.fldClas !== 'null'){ + let oldColClas = JSON.parse(column.fldClas) + for (let i = 0; i < oldColClas.length; i++) { + for (let j = 0; j < showOldColClas.length; j++) { + if (showOldColClas[j].clasPriClas === oldColClas[i].clasPriClas + && showOldColClas[j].clasScdClas === oldColClas[i].clasScdClas + && showOldColClas[j].clasThreClas === oldColClas[i].clasThreClas + && showOldColClas[j].clasName === oldColClas[i].clasName ){ - showNewTabClas[j] = newTabClas[i] + showOldColClas[j] = oldColClas[i] } } } } }else { - showNewTabClas = JSON.parse(data.table.tabClas) + showOldColClas = JSON.parse(column.fldClas) } - newTableInfo.value.showTabClas = showNewTabClas - newColumnList.value = [] - oldColumnList.value = [] - if (data.column && data.column.length > 0){ - for (let i = 0; i < data.column.length; i++) { - let col = data.column[i] - let column = JSON.parse(col.oldColumnData) - let batchColClas = col.batchColClas - let showOldColClas = [] - if (batchColClas && batchColClas.length>0){ - showOldColClas = JSON.parse(JSON.stringify(batchColClas)) - if (column.fldClas && column.fldClas !== '[]' && column.fldClas !== 'null'){ - let oldColClas = JSON.parse(column.fldClas) - for (let i = 0; i < oldColClas.length; i++) { - for (let j = 0; j < showOldColClas.length; j++) { - if (showOldColClas[j].clasPriClas === oldColClas[i].clasPriClas - && showOldColClas[j].clasScdClas === oldColClas[i].clasScdClas - && showOldColClas[j].clasThreClas === oldColClas[i].clasThreClas - && showOldColClas[j].clasName === oldColClas[i].clasName - ){ - showOldColClas[j] = oldColClas[i] - } - } - } - } - }else { - showOldColClas = JSON.parse(column.fldClas) - } - column.showColClas = showOldColClas - oldColumnList.value.push(column) - let showNewColClas = [] - if (batchColClas && batchColClas.length>0){ - showNewColClas = batchColClas - if (col.fldClas && col.fldClas !== '[]' && col.fldClas !== 'null'){ - let newColClas = JSON.parse(col.fldClas) - for (let i = 0; i < newColClas.length; i++) { - for (let j = 0; j < showNewColClas.length; j++) { - if (showNewColClas[j].clasPriClas === newColClas[i].clasPriClas - && showNewColClas[j].clasScdClas === newColClas[i].clasScdClas - && showNewColClas[j].clasThreClas === newColClas[i].clasThreClas - && showNewColClas[j].clasName === newColClas[i].clasName - ){ - showNewColClas[j] = newColClas[i] - } - } + column.showColClas = showOldColClas + oldColumnList.value.push(column) + let showNewColClas = [] + if (batchColClas && batchColClas.length>0){ + showNewColClas = batchColClas + if (col.fldClas && col.fldClas !== '[]' && col.fldClas !== 'null'){ + let newColClas = JSON.parse(col.fldClas) + for (let i = 0; i < newColClas.length; i++) { + for (let j = 0; j < showNewColClas.length; j++) { + if (showNewColClas[j].clasPriClas === newColClas[i].clasPriClas + && showNewColClas[j].clasScdClas === newColClas[i].clasScdClas + && showNewColClas[j].clasThreClas === newColClas[i].clasThreClas + && showNewColClas[j].clasName === newColClas[i].clasName + ){ + showNewColClas[j] = newColClas[i] } } - }else { - showNewColClas = JSON.parse(col.fldClas) } - newColumnList.value.push({ - applyStatus:col.applyStatus, - applyTime:col.applyTime, - crrctPkFlag:col.crrctPkFlag, - crrctVerNum:col.crrctVerNum, - fldClas:col.fldClas, - fldCrrctName:col.fldCrrctName, - fldDesc:col.fldDesc, - fldEngName:col.fldEngName, - fldNullRate:col.fldNullRate, - mdlName:col.mdlName, - onum:col.onum, - pic:col.pic, - recStat:col.recStat, - recSubmPrsn:col.recSubmPrsn, - ssysCd:col.ssysCd, - tabEngName:col.tabEngName, - updTime:col.updTime, - fldCnName:column.fldCnName, - fldType:column.fldType, - dataDictName: col.dataDictName, - dataSecLvl: col.dataSecLvl, - showColClas: showNewColClas - }) } + }else { + showNewColClas = JSON.parse(col.fldClas) + } + newColumnList.value.push({ + applyStatus:col.applyStatus, + applyTime:col.applyTime, + crrctPkFlag:col.crrctPkFlag, + crrctVerNum:col.crrctVerNum, + fldClas:col.fldClas, + fldCrrctName:col.fldCrrctName, + fldDesc:col.fldDesc, + fldEngName:col.fldEngName, + fldNullRate:col.fldNullRate, + mdlName:col.mdlName, + onum:col.onum, + pic:col.pic, + recStat:col.recStat, + recSubmPrsn:col.recSubmPrsn, + ssysCd:col.ssysCd, + tabEngName:col.tabEngName, + updTime:col.updTime, + fldCnName:column.fldCnName, + fldType:column.fldType, + dataDictName: col.dataDictName, + dataSecLvl: col.dataSecLvl, + showColClas: showNewColClas + }) + } + } + businessDialog.value = true +} +function showBusinessDataDialog(row){ + if (row.businessType === 'metaDataInfo'){ + let param = { + businessId: row.businessId + } + getMetaInfoApplyBusinessDetail(param).then(res=>{ + let data = JSON.parse(JSON.stringify(res.data)) + if (data.length === 1){ + transformMetaDetailData(data[0]) + }else if (data.length > 1){ + metaDataList.value = data + metaDataListDialog.value = true } }) }else if(row.businessType ==="dataStdMain"){