diff --git a/vue-fastapi-backend/module_admin/controller/data_ast_content_controller.py b/vue-fastapi-backend/module_admin/controller/data_ast_content_controller.py index 1c1270b..20eec5c 100644 --- a/vue-fastapi-backend/module_admin/controller/data_ast_content_controller.py +++ b/vue-fastapi-backend/module_admin/controller/data_ast_content_controller.py @@ -10,8 +10,10 @@ from module_admin.annotation.log_annotation import Log from module_admin.aspect.interface_auth import CheckUserInterfaceAuth from module_admin.service.login_service import LoginService from module_admin.service.data_ast_content_service import DataCatalogService -from module_admin.entity.vo.data_ast_content_vo import DataCatalogRequest, DataCatalogResponse, DataCatalogPageQueryModel, DeleteDataCatalogModel,DataCatalogResponseWithChildren,DataAssetCatalogTreeResponse,DataCatalogMovedRequest,DataCatalogMergeRequest,DataCatalogChild,DataCatalogMoverelRequest,DataAstIndxRequest,DataAstBookmarkRelaRequest +from module_admin.entity.vo.data_ast_content_vo import DataAstSecuResponse, DataAstSecuRequest,DataCatalogRequest, DataCatalogResponse, DataCatalogPageQueryModel, DeleteDataCatalogModel,DataCatalogResponseWithChildren,DataAssetCatalogTreeResponse,DataCatalogMovedRequest,DataCatalogMergeRequest,DataCatalogChild,DataCatalogMoverelRequest,DataAstIndxRequest,DataAstBookmarkRelaRequest from module_admin.entity.vo.user_vo import CurrentUserModel +from module_admin.entity.vo.metasecurity_vo import MetaSecurityApiModel +from module_admin.service.metasecurity_service import MetaSecurityService from utils.common_util import bytes2file_response from utils.log_util import logger from utils.page_util import PageResponseModel @@ -33,8 +35,9 @@ async def get_data_catalog_list( #设置字段 user_id = current_user.user.user_id + user_name = current_user.user.user_name # 获取分页数据 - catalog_page_query_result = await DataCatalogService.get_catalog_list_services(query_db, catalog_page_query, user_id, is_page=True) + catalog_page_query_result = await DataCatalogService.get_catalog_list_services(query_db, catalog_page_query, user_id, user_name, is_page=True) logger.info('获取成功') @@ -82,6 +85,46 @@ async def add_data_catalog( msg=add_result.message ) +@dataCatalogController.get( + '/getMetaSercuityData', + response_model=DataAstSecuResponse, + dependencies=[Depends(CheckUserInterfaceAuth('system:data_catalog:secu'))] +) +@ValidateFields(validate_model='get_secu_data_request') +async def getMetaSercuityData( + request: Request, + dataAstSecuRequest: DataAstSecuRequest=Depends(DataAstSecuRequest), + query_db: AsyncSession = Depends(get_db), + current_user: CurrentUserModel = Depends(LoginService.get_current_user), + ): + + # 获取当前用户信息 + user_id = current_user.user.user_id + password = current_user.user.password + logger.info(f"获取当前用户信息:user_id={user_id}, password={password}") + + # 设置字段 + apiModel = MetaSecurityApiModel() + apiModel.dbRId = dataAstSecuRequest.data_ast_src + apiModel.username = user_id + apiModel.password = password + apiModel.sqlStr = "select * from " + dataAstSecuRequest.data_ast_eng_name + logger.info(f"设置 apiModel 参数:dbRId={apiModel.dbRId}, username={apiModel.username}, password={apiModel.password}, sqlStr={apiModel.sqlStr}") + + # 打印 apiModel 对象 + logger.debug(f"apiModel 对象内容:{apiModel}") + + # 调用服务层方法 + config_detail_result = await MetaSecurityService.getMetaSercuitybysql(request, query_db, apiModel) + logger.info(f"调用 MetaSecurityService.getMetaSercuitybysql 方法,返回结果:{config_detail_result}") + + # 记录成功日志 + logger.info(f"获取 config_id 为 {apiModel} 的信息成功") + + return ResponseUtil.success(data=config_detail_result) + + + @dataCatalogController.put('/edit', dependencies=[Depends(CheckUserInterfaceAuth('system:data_catalog:edit'))]) @ValidateFields(validate_model='edit_data_catalog') @Log(title='数据目录管理', business_type=BusinessType.UPDATE) @@ -215,7 +258,6 @@ async def delete_ast_book_mark_rela( ): user_name = current_user.user.user_name user_id = current_user.user.user_id - print(123456,user_id,type(user_id)) # 创建请求对象 delete_request = DataAstBookmarkRelaRequest(rela_onum=rela_onum) @@ -244,7 +286,6 @@ async def add_ast_book_mark_rela( user_name = current_user.user.user_name # 调用服务层方法 - print('调用服务层方法',add_bookmark) add_result = await DataCatalogService.add_ast_book_mark_rela_services(query_db, add_bookmark,user_name) logger.info(add_result.message) @@ -269,3 +310,113 @@ async def get_data_ast_indx_list( logger.info('获取成功') return indx_page_query_result + + + + +@dataCatalogController.post('/bookmark/folder', dependencies=[Depends(CheckUserInterfaceAuth('system:data_catalog:add'))]) +@ValidateFields(validate_model='add_bookmark_folder') +@Log(title='收藏目录管理', business_type=BusinessType.INSERT) +async def add_bookmark_folder( + request: Request, + add_folder: DataCatalogRequest, + query_db: AsyncSession = Depends(get_db), + current_user: CurrentUserModel = Depends(LoginService.get_current_user), +): + # 设置字段 + add_folder.upd_prsn = current_user.user.user_name + add_folder.supr_content_onum = 2 # 固定为"我的收藏"的目录ID + add_folder.content_stat = "1" # 设置为有效状态 + add_folder.leaf_node_flag = 1 # 默认为叶子节点 + + # 调用服务层方法 + add_result = await DataCatalogService.add_bookmark_folder_services(query_db, add_folder) + logger.info(add_result.message) + + # 返回标准化响应 + return ResponseUtil.success( + msg=add_result.message + ) + +@dataCatalogController.put('/bookmark/folder', dependencies=[Depends(CheckUserInterfaceAuth('system:data_catalog:edit'))]) +@ValidateFields(validate_model='edit_bookmark_folder') +@Log(title='收藏目录管理', business_type=BusinessType.UPDATE) +async def edit_bookmark_folder( + request: Request, + edit_folder: DataCatalogRequest, + query_db: AsyncSession = Depends(get_db), + current_user: CurrentUserModel = Depends(LoginService.get_current_user), +): + # 设置审计字段 + edit_folder.upd_prsn = current_user.user.user_name + + # 调用服务层方法 + edit_result = await DataCatalogService.edit_bookmark_folder_services(query_db, edit_folder) + logger.info(edit_result.message) + + # 返回标准化响应 + return ResponseUtil.success( + msg=edit_result.message + ) + +@dataCatalogController.delete('/bookmark/folder/{content_onum}', dependencies=[Depends(CheckUserInterfaceAuth('system:data_catalog:remove'))]) +@Log(title='收藏目录管理', business_type=BusinessType.DELETE) +async def delete_bookmark_folder( + request: Request, + content_onum: int, + query_db: AsyncSession = Depends(get_db), + current_user: CurrentUserModel = Depends(LoginService.get_current_user), +): + # 调用服务层方法 + delete_result = await DataCatalogService.delete_bookmark_folder_services( + query_db, + content_onum, + current_user.user.user_name, + current_user.user.user_id + ) + logger.info(delete_result.message) + + # 返回标准化响应 + return ResponseUtil.success( + msg=delete_result.message + ) + +@dataCatalogController.get( + '/bookmark/folders', + dependencies=[Depends(CheckUserInterfaceAuth('system:data_catalog:list'))] +) +async def get_bookmark_folders( + request: Request, + query_db: AsyncSession = Depends(get_db), + current_user: CurrentUserModel = Depends(LoginService.get_current_user), +): + # 获取当前用户名 + user_name = current_user.user.user_name + + # 调用服务层方法 + folders = await DataCatalogService.get_bookmark_folders_services(query_db, user_name) + logger.info(f'获取用户 {user_name} 的收藏目录列表成功') + + # 返回标准化响应 + return ResponseUtil.success(data=folders) + + + +@dataCatalogController.put('/bookmark/asset/move', dependencies=[Depends(CheckUserInterfaceAuth('system:data_catalog:edit'))]) +@ValidateFields(validate_model='move_bookmark_asset') +@Log(title='收藏资产管理', business_type=BusinessType.UPDATE) +async def move_bookmark_asset( + request: Request, + moverel_catalog: DataCatalogMoverelRequest, + query_db: AsyncSession = Depends(get_db), + current_user: CurrentUserModel = Depends(LoginService.get_current_user), +): + # 设置用户信息 + moverel_catalog.upd_prsn = current_user.user.user_name + + # 调用服务层方法 + moverel_result = await DataCatalogService.move_bookmark_asset_services(query_db, moverel_catalog) + logger.info(moverel_result.message) + + # 返回标准化响应 + return ResponseUtil.success(msg=moverel_result.message) diff --git a/vue-fastapi-backend/module_admin/dao/data_ast_content_dao.py b/vue-fastapi-backend/module_admin/dao/data_ast_content_dao.py index 1ca0fe2..1faaa23 100644 --- a/vue-fastapi-backend/module_admin/dao/data_ast_content_dao.py +++ b/vue-fastapi-backend/module_admin/dao/data_ast_content_dao.py @@ -60,6 +60,7 @@ class DataCatalogDAO: return catalog_info + # @classmethod # async def get_catalog_list(cls, db: AsyncSession, query_object: DataCatalogPageQueryModel, user_id: int, is_page: bool = False): # """ @@ -70,101 +71,130 @@ class DataCatalogDAO: # :param is_page: 是否分页 # :return: 数据资产目录分页列表 # """ - # # 创建别名对象 - # t1 = aliased(DataAstContentRela, name='t1') - # t2 = aliased(DataAstInfo, name='t2') - # t3 = aliased(DataAstBookmarkRela, name='t3') - - # query = ( - # select( - # DataAstContent.content_onum, - # DataAstContent.content_name, - # DataAstContent.content_stat, - # DataAstContent.content_intr, - # DataAstContent.content_pic, - # DataAstContent.supr_content_onum, - # DataAstContent.leaf_node_flag, - # DataAstContent.upd_prsn, - # DataAstContent.upd_time, + # 创建别名对象 + # t1 = aliased(DataAstContentRela, name='t1') + # t2 = aliased(DataAstInfo, name='t2') + # t3 = aliased(DataAstBookmarkRela, name='t3') + + # # 修改子查询部分 + # subquery_t1 = ( + # select(DataAstContentRela) + # .where(DataAstContentRela.upd_prsn == query_object.upd_prsn, DataAstContentRela.content_onum == '2' and DataAstContentRela.rela_status == '1') + # .union_all( + # select(DataAstContentRela) + # .where(DataAstContentRela.content_onum != '2' and DataAstContentRela.rela_status == '1') + # ) + # ).alias('subquery_t1') # 为子查询分配唯一别名 + + # query = ( + # select( + # DataAstContent.content_onum, + # DataAstContent.content_name, + # DataAstContent.content_stat, + # DataAstContent.content_intr, + # DataAstContent.content_pic, + # DataAstContent.supr_content_onum, + # DataAstContent.leaf_node_flag, + # DataAstContent.upd_prsn, + # DataAstContent.upd_time, - # t1.rela_onum, - # t1.ast_onum, - # t1.rela_type, - # t1.rela_eff_begn_date, - # t1.rela_eff_end_date, - # t1.upd_prsn, + # subquery_t1.c.rela_onum, # 明确指定子查询的字段 + # subquery_t1.c.ast_onum, + # subquery_t1.c.rela_type, + # subquery_t1.c.rela_eff_begn_date, + # subquery_t1.c.rela_eff_end_date, + # subquery_t1.c.upd_prsn, - # t2.data_ast_no, - # t2.data_ast_eng_name, - # t2.data_ast_cn_name, - # t2.data_ast_type, - # t2.data_ast_stat, - # t2.data_ast_desc, - # t2.data_ast_clas, - # t2.data_ast_cont, - # t2.data_ast_faq, - # t2.data_ast_estb_time, - # t2.data_ast_upd_time, - # t2.data_ast_src, - # t2.ast_no, - # t3.bookmark_orde, - # case( - # (t3.rela_onum.isnot(None), 1), - # else_=0 - # ).label('bookmark_flag') - # ) - # .distinct() - # .select_from(DataAstContent) - # .outerjoin(t1, DataAstContent.content_onum == t1.content_onum) - # .outerjoin(t2, t1.ast_onum == t2.ast_no) - # .outerjoin(t3, and_( - # # t1.rela_onum == t3.rela_onum, - # t2.data_ast_no == t3.data_ast_no, - # t3.user_id == user_id # admin用户的ID,后续以传参的形式过来 - # )) - # .where(DataAstContent.content_stat == 1) - # .order_by(DataAstContent.content_onum) - # ) - - # # 使用分页工具进行查询 - # data_ast_list = await PageUtil.paginate( - # db, - # query, - # page_num=query_object.page_num, - # page_size=query_object.page_size, - # is_page=is_page - # ) - - # return data_ast_list - + # t2.data_ast_no, + # t2.data_ast_eng_name, + # t2.data_ast_cn_name, + # t2.data_ast_type, + # t2.data_ast_stat, + # t2.data_ast_desc, + # t2.data_ast_clas, + # t2.data_ast_cont, + # t2.data_ast_faq, + # t2.data_ast_estb_time, + # t2.data_ast_upd_time, + # t2.data_ast_src, + # t2.ast_no, + # t3.bookmark_orde, + # case( + # (t3.rela_onum.isnot(None), 1), + # else_=0 + # ).label('bookmark_flag') + # ) + # .distinct() + # .select_from(DataAstContent) + # .outerjoin(subquery_t1, DataAstContent.content_onum == subquery_t1.c.content_onum) # 明确使用子查询别名 + # .outerjoin(t2, subquery_t1.c.ast_onum == t2.ast_no) + # .outerjoin(t3, and_( + # subquery_t1.c.ast_onum == t3.data_ast_no, + # t3.user_id == user_id + # )) + # .where(DataAstContent.content_stat == 1) + # .order_by(DataAstContent.content_onum) + # ) + + # # 使用分页工具进行查询 + # data_ast_list = await PageUtil.paginate( + # db, + # query, + # page_num=query_object.page_num, + # page_size=query_object.page_size, + # is_page=is_page + # ) + + # return data_ast_list @classmethod - async def get_catalog_list(cls, db: AsyncSession, query_object: DataCatalogPageQueryModel, user_id: int, is_page: bool = False): - """ - 根据查询参数获取数据资产目录列表 - - :param db: 异步会话对象 - :param query_object: 分页查询参数对象 - :param is_page: 是否分页 - :return: 数据资产目录分页列表 - """ + async def get_catalog_list(cls, db: AsyncSession, query_object: DataCatalogPageQueryModel, user_id: int, user_name: str, is_page: bool = False): # 创建别名对象 t1 = aliased(DataAstContentRela, name='t1') t2 = aliased(DataAstInfo, name='t2') t3 = aliased(DataAstBookmarkRela, name='t3') - # 修改子查询部分 + # 构建子查询1(对应subquery_t1) subquery_t1 = ( - select(DataAstContentRela) - .where(DataAstContentRela.upd_prsn == query_object.upd_prsn, DataAstContentRela.content_onum == '2' and DataAstContentRela.rela_status == '1') + select(t1) + .where( + t1.upd_prsn == user_name, + t1.content_onum == '2', + t1.rela_status == '1' + ) .union_all( - select(DataAstContentRela) - .where(DataAstContentRela.content_onum != '2' and DataAstContentRela.rela_status == '1') + select(t1) + .where( + t1.content_onum != '2', + t1.rela_status == '1' + ) + ) + ).alias('subquery_t1') + + # 新增子查询2(对应subquery_t2) + subquery_t2 = ( + select(t1.rela_onum) + .where( + t1.rela_status == 1, + t1.upd_prsn == user_name, #query_object.upd_prsn + t1.content_onum.in_( + select(DataAstContent.content_onum) + .where( + or_( + DataAstContent.supr_content_onum == 2, + DataAstContent.content_onum == 2 + ), + DataAstContent.content_stat == 1, + DataAstContent.upd_prsn == user_name + ) + ) ) - ).alias('subquery_t1') # 为子查询分配唯一别名 + ).alias('subquery_t2') + # 主查询构建 query = ( select( + # 原有字段保持不变 DataAstContent.content_onum, DataAstContent.content_name, DataAstContent.content_stat, @@ -175,13 +205,14 @@ class DataCatalogDAO: DataAstContent.upd_prsn, DataAstContent.upd_time, - subquery_t1.c.rela_onum, # 明确指定子查询的字段 + subquery_t1.c.rela_onum, subquery_t1.c.ast_onum, subquery_t1.c.rela_type, subquery_t1.c.rela_eff_begn_date, subquery_t1.c.rela_eff_end_date, subquery_t1.c.upd_prsn, + # 修正:直接使用t2的属性,而非t2.c t2.data_ast_no, t2.data_ast_eng_name, t2.data_ast_cn_name, @@ -195,25 +226,32 @@ class DataCatalogDAO: t2.data_ast_upd_time, t2.data_ast_src, t2.ast_no, + t3.bookmark_orde, case( - (t3.rela_onum.isnot(None), 1), + (t3.rela_onum != None, 1), else_=0 - ).label('bookmark_flag') + ).label('bookmark_flag'), + case( + (subquery_t2.c.rela_onum != None, 1), + else_=0 + ).label('sczc_flag') ) .distinct() .select_from(DataAstContent) - .outerjoin(subquery_t1, DataAstContent.content_onum == subquery_t1.c.content_onum) # 明确使用子查询别名 + .outerjoin(subquery_t1, DataAstContent.content_onum == subquery_t1.c.content_onum) .outerjoin(t2, subquery_t1.c.ast_onum == t2.ast_no) .outerjoin(t3, and_( subquery_t1.c.ast_onum == t3.data_ast_no, t3.user_id == user_id )) - .where(DataAstContent.content_stat == 1) + .outerjoin(subquery_t2, subquery_t1.c.rela_onum == subquery_t2.c.rela_onum) + .where( + DataAstContent.content_stat == 1 + ) .order_by(DataAstContent.content_onum) ) - - # 使用分页工具进行查询 + # 分页处理保持不变 data_ast_list = await PageUtil.paginate( db, query, @@ -221,12 +259,9 @@ class DataCatalogDAO: page_size=query_object.page_size, is_page=is_page ) - return data_ast_list - - @classmethod async def add_catalog_dao(cls, db: AsyncSession, catalog1: dict, catalog2: dict): """ @@ -411,26 +446,30 @@ class DataCatalogDAO: :param db: 异步会话对象 :return: 去重后的数据资产树数据 """ + # 创建别名对象 + a = aliased(DataAstInfo, name='a') + b = aliased(DataAstContentRela, name='b') + + # 构建查询 query = ( select( - DataAstInfo.data_ast_src, - DataAstInfo.data_ast_eng_name, - DataAstInfo.data_ast_cn_name, - DataAstInfo.ast_no + a.data_ast_src, + a.data_ast_eng_name, + a.data_ast_cn_name, + a.ast_no, + case( + (b.ast_onum.isnot(None), 1), + else_=0 + ).label('rel_status') ) .distinct() - .select_from(DataAstInfo) - .where( - DataAstInfo.data_ast_stat == 1, - not_( - DataAstInfo.ast_no.in_( - select(DataAstContentRela.ast_onum) - .where(DataAstContentRela.rela_status == 1) - ) - ) - ) + .select_from(a) + .outerjoin(b, and_( + a.ast_no == b.ast_onum, + b.rela_status == 1 + )) + .where(a.data_ast_stat == 1) ) - result = await db.execute(query) rows = result.fetchall() @@ -472,16 +511,6 @@ class DataCatalogDAO: :return: """ - # stmt = ( - # update(DataAstContent) - # .where(DataAstContent.content_onum == merge_catalog_data['content_onum'] , DataAstContent.supr_content_onum == merge_catalog_data['supr_content_onum']) - # .values( - # content_onum=merge_catalog_data['content_onum_after'], - # supr_content_onum=merge_catalog_data['supr_content_onum_after'], - # upd_time=datetime.now() - # ) ) - - # await db.execute(stmt) stmt1 = ( update(DataAstContentRela) .where( DataAstContentRela.content_onum == merge_catalog_data['content_onum'] and DataAstContentRela.rela_status == 1 ) @@ -585,27 +614,61 @@ class DataCatalogDAO: :return: 操作结果字典(包含成功状态和提示信息) """ try: + # 打印传入的参数 + logger.info(f"开始处理取消收藏请求,传入参数:catalog={catalog}, user_name={user_name}, user_id={user_id}") + # 创建子查询:获取需要删除的资产编号 ast_onum_subquery = ( select(DataAstContentRela.ast_onum) .where( DataAstContentRela.rela_onum == catalog['rela_onum'], - DataAstBookmarkRela.user_id == user_id, + DataAstContentRela.upd_prsn == user_name, DataAstContentRela.rela_status == '1' ) ).subquery() + + # 创建子查询:获取在收藏目录下的序号content_onum + content_onum_subquery = ( + select(DataAstContent.content_onum) + .where( + DataAstContent.content_onum == '2' or DataAstContent.supr_content_onum == '2', + DataAstContent.content_stat == '1', + DataAstContent.upd_prsn == user_name + ).subquery() + ) + + # 创建子查询 + content_onum_subquery = ( + select(DataAstContent.content_onum) + .where( + and_( + or_( + DataAstContent.content_onum == '2', + DataAstContent.supr_content_onum == '2' + ), + DataAstContent.content_stat == '1', + DataAstContent.upd_prsn == user_name + ) + ) + .subquery() + ) + # 打印子查询的SQL语句 + logger.info(f"子查询SQL: {str(ast_onum_subquery),str(content_onum_subquery)}") # 构建删除语句 stmt1 = ( delete(DataAstContentRela) .where( DataAstContentRela.upd_prsn == user_name, - DataAstContentRela.content_onum == '2', # 考虑使用变量或常量 - DataAstContentRela.ast_onum.in_(ast_onum_subquery), - DataAstContentRela.rela_status == 1 + DataAstContentRela.rela_status == 1, + DataAstContentRela.content_onum.in_(content_onum_subquery), + DataAstContentRela.ast_onum.in_(ast_onum_subquery) ) ) + # 打印删除语句1的SQL + logger.info(f"删除语句1 SQL: {str(stmt1)}") + stmt2 = ( delete(DataAstBookmarkRela) .where( @@ -614,9 +677,14 @@ class DataCatalogDAO: ) ) + # 打印删除语句2的SQL + logger.info(f"删除语句2 SQL: {str(stmt2)}") + # 执行删除操作 - await db.execute(stmt1) + logger.info("开始执行删除操作...") + await db.execute(stmt2) + await db.execute(stmt1) await db.commit() logger.info(f"成功删除收藏关系") @@ -632,6 +700,8 @@ class DataCatalogDAO: return {"is_success": False, "message": "未知错误"} + + @classmethod async def delete_ast_book_mark_rela_by_content_onum(cls, db: AsyncSession, content_onum: int, user_id: int): """ @@ -671,21 +741,6 @@ class DataCatalogDAO: - # @classmethod - # async def add_ast_book_mark_rela_dao(cls, db: AsyncSession, catalog: DataAstBookmarkRelaRequest): - # """ - # 添加收藏数据库操作 - - # :param db: orm对象 - # :param catalog: 收藏对象 - # :return: - # """ - # #如果catalog[user_id]下已经存在了catalog[data_ast_no],那么返回已收藏,否则添加收藏,新添加的收藏顺序号要求是插入之前最大顺序号加1 - # db_catalog = DataAstBookmarkRela(**catalog) - # db.add(db_catalog) - # await db.flush() - # logger.info(" 添加收藏,操作成功") - @classmethod async def add_ast_book_mark_rela_dao(cls, db: AsyncSession, catalog: DataAstBookmarkRelaRequest, user_name: str): """ @@ -791,4 +846,292 @@ class DataCatalogDAO: result = await db.execute(query) rows = result.mappings().all() # 直接获取字典列表 - return rows \ No newline at end of file + return rows + + + + @classmethod + async def get_bookmark_folder_by_name(cls, db: AsyncSession, folder_name: str, user_name: str): + """ + 根据名称和用户名获取收藏目录 + + :param db: 数据库会话 + :param folder_name: 目录名称 + :param user_name: 用户名 + :return: 目录对象 + """ + query = ( + select(DataAstContent) + .where( + DataAstContent.content_name == folder_name, + DataAstContent.upd_prsn == user_name, + DataAstContent.supr_content_onum == 2, + DataAstContent.content_stat == "1" + ) + ) + + result = await db.execute(query) + return result.scalars().first() + + + @classmethod + async def get_bookmark_folder_by_id(cls, db: AsyncSession, content_onum: int, user_name: str): + """ + 根据ID和用户名获取收藏目录 + + :param db: 数据库会话 + :param content_onum: 目录ID + :param user_name: 用户名 + :return: 目录对象 + """ + query = ( + select(DataAstContent) + .where( + DataAstContent.content_onum == content_onum, + DataAstContent.upd_prsn == user_name, + DataAstContent.supr_content_onum == 2, + DataAstContent.content_stat == "1" + ) + ) + + result = await db.execute(query) + return result.scalars().first() + + + @classmethod + async def check_folder_has_relations(cls, db: AsyncSession, content_onum: int): + """ + 检查目录下是否有资产关系 + + :param db: 数据库会话 + :param content_onum: 目录ID + :return: 是否存在关系 + """ + query = ( + select(func.count(DataAstContentRela.rela_onum)) + .where( + DataAstContentRela.content_onum == content_onum, + DataAstContentRela.rela_status == "1" + ) + ) + + result = await db.execute(query) + count = result.scalar() + return count > 0 + + @classmethod + async def get_bookmark_folders(cls, db: AsyncSession, user_name: str): + """ + 获取用户的收藏目录列表 + + :param db: 数据库会话 + :param user_name: 用户名 + :return: 目录列表 + """ + # 构建联合查询 + combined_query = ( + select( + DataAstContent.content_onum, + DataAstContent.content_name, + DataAstContent.content_intr, + DataAstContent.content_pic, + DataAstContent.upd_time, + DataAstContent.supr_content_onum, + DataAstContent.leaf_node_flag + ) + # 根目录条件 + .where( + DataAstContent.content_onum == 2, + DataAstContent.content_stat == "1" + ) + # 合并子目录条件 + .union_all( + select( + DataAstContent.content_onum, + DataAstContent.content_name, + DataAstContent.content_intr, + DataAstContent.content_pic, + DataAstContent.upd_time, + DataAstContent.supr_content_onum, + DataAstContent.leaf_node_flag + ) + .where( + DataAstContent.upd_prsn == user_name, + DataAstContent.supr_content_onum == 2, + DataAstContent.content_stat == "1" + ) + .order_by(DataAstContent.upd_time.desc()) + ) + ) + + result = await db.execute(combined_query) + return [dict(row) for row in result.mappings().all()] + + + @classmethod + async def get_bookmark_folder_by_name_exclude_id(cls, db: AsyncSession, folder_name: str, user_name: str, exclude_id: int): + """ + 根据名称和用户名获取收藏目录,排除指定ID + + :param db: 数据库会话 + :param folder_name: 目录名称 + :param user_name: 用户名 + :param exclude_id: 排除的目录ID + :return: 目录对象 + """ + query = ( + select(DataAstContent) + .where( + DataAstContent.content_name == folder_name, + DataAstContent.upd_prsn == user_name, + DataAstContent.supr_content_onum == 2, + DataAstContent.content_stat == "1", + DataAstContent.content_onum != exclude_id + ) + ) + + result = await db.execute(query) + return result.scalars().first() + + + + @classmethod + async def is_bookmark_folder(cls, db: AsyncSession, content_onum: int, user_name: str = None): + """ + 检查目录是否是收藏目录或其子目录 + + :param db: 数据库会话 + :param content_onum: 目录ID + :param user_name: 用户名(如果需要验证所有权) + :return: 是否是收藏目录 + """ + if content_onum == 2: # "我的收藏"根目录 + return True + + query = select(DataAstContent).where( + DataAstContent.content_onum == content_onum, + DataAstContent.supr_content_onum == 2, + DataAstContent.content_stat == "1" + ) + + if user_name: + query = query.where(DataAstContent.upd_prsn == user_name) + + result = await db.execute(query) + return result.scalars().first() is not None + + @classmethod + async def move_bookmark_asset_dao(cls, db: AsyncSession, moverel_catalog_data: dict): + """ + 在收藏目录间移动资产的数据库操作 + """ + stmt = ( + update(DataAstContentRela) + .where( + DataAstContentRela.rela_onum == moverel_catalog_data['rela_onum'], + DataAstContentRela.content_onum == moverel_catalog_data['content_onum'], + DataAstContentRela.rela_status == "1" + ) + .values( + content_onum=moverel_catalog_data['content_onum_after'], + upd_prsn=moverel_catalog_data['upd_prsn'], + rela_eff_end_date=datetime.now() + ) + ) + + await db.execute(stmt) + await cls.update_leaf_node_flag(db) + + + @classmethod + async def delete_bookmark_folder_dao(cls, db: AsyncSession, content_onum: int, user_name: str,user_id:str): + """ + 删除收藏目录及其资产关系的专用数据库操作 + + :param db: orm对象 + :param content_onum: 收藏目录ID + :param user_name: 用户名(用于权限验证) + :return: 操作结果字典 + """ + try: + logger.info(f"开始删除用户 {user_name} 的收藏目录 {content_onum}") + + # 1. 验证目录是否存在且属于当前用户和收藏体系 + folder_query = select(DataAstContent).where( + DataAstContent.content_onum == content_onum, + DataAstContent.upd_prsn == user_name, # 确保只能删除自己的收藏目录 + DataAstContent.supr_content_onum == 2, # 确保是收藏子目录 + DataAstContent.content_stat == '1' + ) + folder_result = await db.execute(folder_query) + folder = folder_result.scalars().first() + + if not folder: + logger.warning(f"未找到用户 {user_name} 的收藏目录 {content_onum} 或无权限删除") + return {"success": False, "message": "收藏目录不存在或无权限删除"} + + # 创建子查询,获取符合条件的 ast_onum + ast_onum_subs = ( + select(DataAstContentRela.ast_onum) + .where( + DataAstContentRela.content_onum == content_onum, + DataAstContentRela.rela_status == '1', + DataAstContentRela.upd_prsn == user_name + ) + .subquery() + ) + + # 删除收藏关系表数据 + delete_stmt = ( + delete(DataAstBookmarkRela) + .where( + DataAstBookmarkRela.data_ast_no.in_(ast_onum_subs), + DataAstBookmarkRela.user_id == user_id + ) + ) + # 执行删除操作 + await db.execute(delete_stmt) + + # 2. 更新关联的资产关系状态 + rela_update = await db.execute( + update(DataAstContentRela) + .where( + DataAstContentRela.content_onum == content_onum, + DataAstContentRela.upd_prsn == user_name, + DataAstContentRela.rela_status == '1' + ) + .values( + rela_status='0', + rela_eff_end_date=datetime.now() + ) + ) + rela_count = rela_update.rowcount + logger.info(f"已更新 {rela_count} 个资产关系状态") + + # 3. 更新目录状态为无效 + folder_update = await db.execute( + update(DataAstContent) + .where( + DataAstContent.content_onum == content_onum, + DataAstContent.upd_prsn == user_name, + DataAstContent.content_stat == '1' + ) + .values( + content_stat='0', + upd_time=datetime.now() + ) + ) + + + + + # 4. 更新叶子节点标志 + await cls.update_leaf_node_flag(db) + await db.commit() + + logger.info(f"成功删除用户 {user_name} 的收藏目录 {content_onum}") + return {"success": True, "message": "收藏目录删除成功"} + + except Exception as e: + logger.error(f"删除收藏目录时发生错误: {str(e)}", exc_info=True) + return {"success": False, "message": f"删除操作出错: {str(e)}"} \ No newline at end of file diff --git a/vue-fastapi-backend/module_admin/entity/vo/data_ast_content_vo.py b/vue-fastapi-backend/module_admin/entity/vo/data_ast_content_vo.py index 5fff00e..ff11c2a 100644 --- a/vue-fastapi-backend/module_admin/entity/vo/data_ast_content_vo.py +++ b/vue-fastapi-backend/module_admin/entity/vo/data_ast_content_vo.py @@ -167,6 +167,7 @@ class DataCatalogMoverelRequest(BaseModel): rela_onum: Optional[int] = Field(default=None, alias="relaOnum", description='关系序号') content_onum: Optional[int] = Field(default=None, alias="contentOnum", description='目录序号') content_onum_after: Optional[int] = Field(default=None, alias="contentOnumAfter", description='移动后的目录序号') + upd_prsn: Optional[str] = Field(default=None, alias="updPrsn", description='更新人员') class DataAstBookmarkRelaRequest(BaseModel): @@ -203,4 +204,16 @@ class DataAstIndxResponse(BaseModel): ast_no: Optional[str] = Field(default=None, alias="astNo", description='资产编号') indx_no: Optional[str] = Field(default=None, alias="indxNo", description='指标编号') indx_name: Optional[str] = Field(default=None, alias="indxName", description='指标名称') - indx_val: Optional[float] = Field(default=None, alias="indxVal", description='指标值') \ No newline at end of file + indx_val: Optional[float] = Field(default=None, alias="indxVal", description='指标值') + +class DataAstSecuRequest(BaseModel): + model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True, from_attributes=True) + + data_ast_src: Optional[str] = Field(default=None, alias="dataAstSrc", description='数据源连接') + data_ast_eng_name: Optional[str] = Field(default=None, alias="dataAstEngName", description='表英文名') + +class DataAstSecuResponse(BaseModel): + model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True, from_attributes=True) + + data_ast_src: Optional[str] = Field(default=None, alias="dataAstSrc", description='数据源连接') + data_ast_eng_name: Optional[str] = Field(default=None, alias="dataAstEngName", description='表英文名') \ No newline at end of file diff --git a/vue-fastapi-backend/module_admin/service/data_ast_content_service.py b/vue-fastapi-backend/module_admin/service/data_ast_content_service.py index 6a505fe..e6fa793 100644 --- a/vue-fastapi-backend/module_admin/service/data_ast_content_service.py +++ b/vue-fastapi-backend/module_admin/service/data_ast_content_service.py @@ -1,9 +1,10 @@ from datetime import datetime from utils.log_util import logger from collections import defaultdict -from pyecharts.options import LabelOpts +from pyecharts.options import LabelOpts, InitOpts from fastapi.responses import JSONResponse from pyecharts.charts import Pie, Bar, Page +from pyecharts import options as opts from sqlalchemy.ext.asyncio import AsyncSession from exceptions.exception import ServiceException from module_admin.dao.data_ast_content_dao import DataCatalogDAO @@ -18,7 +19,7 @@ class DataCatalogService: @classmethod async def get_catalog_list_services( - cls, query_db: AsyncSession, query_object: DataCatalogPageQueryModel, user_id: int, is_page: bool = False + cls, query_db: AsyncSession, query_object: DataCatalogPageQueryModel, user_id: int, user_name: str, is_page: bool = False ): """ 获取数据目录列表信息service @@ -28,8 +29,8 @@ class DataCatalogService: :param is_page: 是否开启分页 :return: 数据目录列表信息对象 """ - catalog_list_result = await DataCatalogDAO.get_catalog_list(query_db, query_object, user_id, is_page) - + catalog_list_result = await DataCatalogDAO.get_catalog_list(query_db, query_object, user_id, user_name, is_page) + print('获取数据清单内容111:',catalog_list_result) # 按contentOnum分组 grouped = defaultdict(list) for item in catalog_list_result.rows: @@ -60,6 +61,7 @@ class DataCatalogService: # 处理叶子节点的数据资产子节点 if is_leaf and rela_onum : for item in items: + asset_child = { 'relaOnum': item['relaOnum'], 'contentOnum': first_item['contentOnum'], @@ -83,7 +85,8 @@ class DataCatalogService: 'astNo': item['astNo'], 'relaOnum': item['relaOnum'], 'bookmarkOrde': item['bookmarkOrde'], - 'bookmarkFlag': item['bookmarkFlag'] + 'bookmarkFlag': item['bookmarkFlag'], + 'sczcFlag': item['sczcFlag'] } common_fields['children'].append(asset_child) @@ -99,9 +102,6 @@ class DataCatalogService: parent = nodes.get(supr) if parent: parent['children'].append(node) - - print('获取数据清单内容:',root) - catalog_list_result.rows = [root] return catalog_list_result @@ -274,7 +274,7 @@ class DataCatalogService: sys_groups = {} for item in rows: - sys_name, eng_name, cn_name, ast_no = item + sys_name, eng_name, cn_name, ast_no, rel_status = item # 创建或获取系统分组 if sys_name not in sys_groups: sys_groups[sys_name] = { @@ -286,7 +286,8 @@ class DataCatalogService: sys_groups[sys_name]["children"].append({ "dataAssetCatalogNo": eng_name, "dataAssetCatalogName": cn_name, - "dataAssetCatalogAstno": ast_no + "dataAssetCatalogAstno": ast_no, + "rel_status": rel_status }) results = list(sys_groups.values()) # 转换为最终列表格式 @@ -410,23 +411,6 @@ class DataCatalogService: logger.error(" 取消收藏,操作失败") - # @classmethod - # async def add_ast_book_mark_rela_services(cls, db: AsyncSession, request: DataAstBookmarkRelaRequest): - # """ - # 添加收藏数据库操作 - - # """ - # add_rela_onum = { - # 'user_id': request.user_id, - # 'data_ast_no': request.data_ast_no - # } - # try: - # await DataCatalogDAO.add_ast_book_mark_rela_dao(db, add_rela_onum) - # await db.commit() - # return CrudResponseModel(is_success=True, message='添加收藏,操作成功') - # except Exception as e: - # await db.rollback() - # logger.error(" 添加收藏,操作失败") @classmethod async def add_ast_book_mark_rela_services(cls, db: AsyncSession, request: DataAstBookmarkRelaRequest, user_name: str): @@ -442,7 +426,7 @@ class DataCatalogService: add_rela_onum = { 'user_id': request.user_id, 'data_ast_no': request.data_ast_no, # 我的收藏 - 'content_onum': 2, + 'content_onum': request.content_onum, 'rela_type': "归属关系", 'rela_eff_begn_date': datetime.now().strftime("%Y-%m-%d %H:%M:%S"), # 设置默认值,当前时间 'rela_eff_end_date': datetime(year=2999, month=12, day=31, hour=0, minute=0, second=0).strftime("%Y-%m-%d %H:%M:%S") @@ -494,43 +478,285 @@ class DataCatalogService: message=f"收藏操作失败: {str(e)}" ) + + # 添加到 DataCatalogService 类中 + @classmethod - async def get_data_ast_indx_list_services(cls, query_db: AsyncSession, query_object: DataAstIndxRequest): + async def add_bookmark_folder_services(cls, db: AsyncSession, folder: DataCatalogRequest): + """ + 添加收藏子目录服务 + + :param db: 数据库会话 + :param folder: 目录请求对象 + :return: 操作结果 + """ + try: + # 检查是否已存在同名目录 + existing_folder = await DataCatalogDAO.get_bookmark_folder_by_name( + db, + folder.content_name, + folder.upd_prsn + ) + + if existing_folder: + return CrudResponseModel(is_success=False, message="已存在同名收藏目录") + + # 转换为字典并添加 + folder_dict = folder.model_dump(exclude_unset=True) + result = await DataCatalogDAO.add_catalog_dao(db, folder_dict, {"children": []}) + + # 提交事务 + await db.commit() + + return CrudResponseModel(is_success=True, message="收藏目录添加成功") + except Exception as e: + await db.rollback() + logger.error(f"添加收藏目录失败: {str(e)}", exc_info=True) + return CrudResponseModel(is_success=False, message=f"添加收藏目录失败: {str(e)}") + @classmethod + async def edit_bookmark_folder_services(cls, db: AsyncSession, folder: DataCatalogRequest): """ - 获取数据资产指标列表信息service + 修改收藏子目录服务 + + :param db: 数据库会话 + :param folder: 目录请求对象 + :return: 操作结果 """ try: - indx_list_dict = await DataCatalogDAO.get_data_ast_indx_list(query_db, query_object) + # 检查目录是否存在且属于当前用户 + existing_folder = await DataCatalogDAO.get_bookmark_folder_by_id( + db, + folder.content_onum, + folder.upd_prsn + ) + + if not existing_folder: + return CrudResponseModel(is_success=False, message="收藏目录不存在或无权限修改") + + # 检查是否已存在同名目录(排除自身) + same_name_folder = await DataCatalogDAO.get_bookmark_folder_by_name_exclude_id( + db, + folder.content_name, + folder.upd_prsn, + folder.content_onum + ) + + if same_name_folder: + return CrudResponseModel(is_success=False, message="已存在同名收藏目录") + + # 转换为字典并更新 + folder_dict = folder.model_dump(exclude_unset=True) + folder_dict.update({ + "supr_content_onum": 2, # 确保父目录不变 + "content_stat": "1", # 添加状态字段 + "leaf_node_flag": 1, # 添加叶子节点标志 + "content_intr": folder_dict.get("content_intr", None), # 可选字段 + "content_pic": folder_dict.get("content_pic", None) # 可选字段 + }) + + await DataCatalogDAO.edit_catalog_dao(db, folder_dict) + + # 提交事务 + await db.commit() + + return CrudResponseModel(is_success=True, message="收藏目录修改成功") + except Exception as e: + await db.rollback() + logger.error(f"修改收藏目录失败: {str(e)}", exc_info=True) + return CrudResponseModel(is_success=False, message=f"修改收藏目录失败: {str(e)}") + + @classmethod + async def delete_bookmark_folder_services(cls, db: AsyncSession, content_onum: int, user_name: str,user_id:str): + """ + 删除收藏子目录服务 + + :param db: 数据库会话 + :param content_onum: 目录ID + :param user_name: 用户名 + :return: 操作结果 + """ + try: + # 检查目录是否存在且属于当前用户 + existing_folder = await DataCatalogDAO.get_bookmark_folder_by_id( + db, + content_onum, + user_name + ) + + if not existing_folder: + return CrudResponseModel(is_success=False, message="收藏目录不存在或无权限删除") + + + # 使用专用方法执行删除操作 + delete_result = await DataCatalogDAO.delete_bookmark_folder_dao(db, content_onum, user_name,user_id) + + if not delete_result["success"]: + return CrudResponseModel(is_success=False, message=delete_result["message"]) + + # 提交事务 + await db.commit() + + return CrudResponseModel(is_success=True, message="收藏目录删除成功") + except Exception as e: + await db.rollback() + logger.error(f"删除收藏目录失败: {str(e)}", exc_info=True) + return CrudResponseModel(is_success=False, message=f"删除收藏目录失败: {str(e)}") + + @classmethod + async def get_bookmark_folders_services(cls, db: AsyncSession, user_name: str): + """ + 获取用户收藏目录列表服务 + + :param db: 数据库会话 + :param user_name: 用户名 + :return: 目录列表 + """ + try: + # 获取用户的收藏目录列表 + folders = await DataCatalogDAO.get_bookmark_folders(db, user_name) + return folders + except Exception as e: + logger.error(f"获取收藏目录列表失败: {str(e)}", exc_info=True) + return [] + - # 提取指标数据 + @classmethod + async def move_bookmark_asset_services(cls, query_db: AsyncSession, request: DataCatalogMoverelRequest): + """ + 在收藏目录间移动资产服务 + """ + try: + # 1. 验证源目录和目标目录是否都属于收藏体系 + source_is_bookmark = await DataCatalogDAO.is_bookmark_folder(query_db, request.content_onum, request.upd_prsn) + target_is_bookmark = await DataCatalogDAO.is_bookmark_folder( + query_db, + request.content_onum_after, + request.upd_prsn + ) + + if not source_is_bookmark: + return CrudResponseModel(is_success=False, message="源目录不是收藏目录") + + if not target_is_bookmark: + return CrudResponseModel(is_success=False, message="目标目录不是收藏目录或不属于当前用户") + + # 2. 构建移动数据 + moverel_catalog_data = { + 'rela_onum': request.rela_onum, + 'content_onum': request.content_onum, + 'content_onum_after': request.content_onum_after, + 'upd_prsn': request.upd_prsn + } + + # 3. 执行移动操作 + await DataCatalogDAO.move_bookmark_asset_dao(query_db, moverel_catalog_data) + await query_db.commit() + + return CrudResponseModel(is_success=True, message="收藏资产移动成功") + + except Exception as e: + await query_db.rollback() + logger.error(f"移动收藏资产失败: {str(e)}", exc_info=True) + return CrudResponseModel(is_success=False, message=f"移动收藏资产失败: {str(e)}") + + + @classmethod + async def get_data_ast_indx_list_services(cls, query_db: AsyncSession, query_object: DataAstIndxRequest): + """获取数据资产指标列表信息service""" + try: + indx_list_dict = await DataCatalogDAO.get_data_ast_indx_list(query_db, query_object) indx_names = [item["indx_name"] for item in indx_list_dict] indx_vals = [item["indx_val"] for item in indx_list_dict] - # 创建图表 + # 创建独立图表 pie = ( - Pie() + Pie(init_opts=InitOpts(width="100%", height="180px")) .add("", list(zip(indx_names, indx_vals))) - .set_global_opts(title_opts={"text": "指标饼图"}) + .set_global_opts( + title_opts=opts.TitleOpts(title="指标饼图", padding=[5,0,0,0]), + legend_opts=opts.LegendOpts( + type_="scroll", + orient="vertical", + pos_right="2%", + pos_top="10%" + ) + ) .set_series_opts(label_opts=LabelOpts(formatter="{b}: {c}")) ) bar = ( - Bar() + Bar(init_opts=InitOpts(width="100%", height="250px")) .add_xaxis(indx_names) .add_yaxis("指标值", indx_vals) - .set_global_opts(title_opts={"text": "指标柱状图"}) + .set_global_opts( + title_opts=opts.TitleOpts(title="指标柱状图", padding=[20,0,0,0]), + datazoom_opts=[opts.DataZoomOpts(type_="inside")] + ) ) - # 组合图表 - page = Page() - page.add(pie, bar) + # 生成独立图表HTML + pie_html = pie.render_embed() + bar_html = bar.render_embed() + + # 构建最终HTML结构 + responsive_html = f""" + + + + + + + + + +
+ {pie_html} +
+ {bar_html} +
+
+ + + + """ + except Exception as e: logger.error(f"获取数据资产指标列表信息失败: {str(e)}") raise ServiceException(message=f"获取数据资产指标列表信息失败: {str(e)}") else: - return page.render_embed() - logger.info(f"获取数据资产指标列表信息成功") - - - + return responsive_html diff --git a/vue-fastapi-frontend/src/api/dataAsset/directory.js b/vue-fastapi-frontend/src/api/dataAsset/directory.js index dd487c7..2b530be 100644 --- a/vue-fastapi-frontend/src/api/dataAsset/directory.js +++ b/vue-fastapi-frontend/src/api/dataAsset/directory.js @@ -53,14 +53,6 @@ export function cancelDirectoryCollection(id) { }) } -export function delDirectoryCollection(data) { - return request({ - url: '/default-api/system/delete_data_asset_collection', - method: 'delete', - data, - }) -} - export function moveDirectory(data) { return request({ url: '/default-api/system/data_catalog/moved', @@ -108,3 +100,57 @@ export function getHtmlString(params) { params, }) } + +export function getMetaSecurityData(params) { + return request({ + url: '/default-api/system/data_catalog/getMetaSercuityData', + method: 'get', + params, + }) +} + +export function moveBookmarkAsset(data) { + return request({ + url: '/default-api/system/data_catalog/bookmark/asset/move', + method: 'put', + data, + }) +} + +export function getBookmarkFolder(params) { + return request({ + url: '/default-api/system/data_catalog/bookmark/folders', + method: 'get', + params, + }) +} + +export function deleteBookmarkFolder(id) { + return request({ + url: `/default-api/system/data_catalog/bookmark/folder/${id}`, + method: 'delete', + }) +} + +export function addBookmarkFolder(data) { + return request({ + url: '/default-api/system/data_catalog/bookmark/folder ', + method: 'post', + data, + }) +} + +export function updateBookmarkFolder(data) { + return request({ + url: '/default-api/system/data_catalog/bookmark/folder ', + method: 'put', + data, + }) +} + +export function getAssetFieldTable(id) { + return request({ + url: `/default-api/dasset/meta/getTable/${id}`, + method: 'get', + }) +} diff --git a/vue-fastapi-frontend/src/views/dataAsset/directory/components/AssetBookmarkDialog.vue b/vue-fastapi-frontend/src/views/dataAsset/directory/components/AssetBookmarkDialog.vue new file mode 100644 index 0000000..8c61c2d --- /dev/null +++ b/vue-fastapi-frontend/src/views/dataAsset/directory/components/AssetBookmarkDialog.vue @@ -0,0 +1,105 @@ + + + diff --git a/vue-fastapi-frontend/src/views/dataAsset/directory/components/AssetMoveDialog.vue b/vue-fastapi-frontend/src/views/dataAsset/directory/components/AssetMoveDialog.vue index 0a0209d..8ccab32 100644 --- a/vue-fastapi-frontend/src/views/dataAsset/directory/components/AssetMoveDialog.vue +++ b/vue-fastapi-frontend/src/views/dataAsset/directory/components/AssetMoveDialog.vue @@ -107,7 +107,7 @@ const disabled = ref(false) const { proxy } = getCurrentInstance() const form = ref({}) const rules = ref({ - targetContentOnum: [ + contentOnumAfter: [ { required: true, message: '目标目录不能为空', trigger: 'blur' }, ], }) diff --git a/vue-fastapi-frontend/src/views/dataAsset/directory/components/BookmarkFormDialog.vue b/vue-fastapi-frontend/src/views/dataAsset/directory/components/BookmarkFormDialog.vue new file mode 100644 index 0000000..901001e --- /dev/null +++ b/vue-fastapi-frontend/src/views/dataAsset/directory/components/BookmarkFormDialog.vue @@ -0,0 +1,82 @@ + + + diff --git a/vue-fastapi-frontend/src/views/dataAsset/directory/components/BookmarkMoveDialog.vue b/vue-fastapi-frontend/src/views/dataAsset/directory/components/BookmarkMoveDialog.vue new file mode 100644 index 0000000..53a1872 --- /dev/null +++ b/vue-fastapi-frontend/src/views/dataAsset/directory/components/BookmarkMoveDialog.vue @@ -0,0 +1,117 @@ + + + + + diff --git a/vue-fastapi-frontend/src/views/dataAsset/directory/components/FormDialog.vue b/vue-fastapi-frontend/src/views/dataAsset/directory/components/FormDialog.vue index 5ffed82..52d8b78 100644 --- a/vue-fastapi-frontend/src/views/dataAsset/directory/components/FormDialog.vue +++ b/vue-fastapi-frontend/src/views/dataAsset/directory/components/FormDialog.vue @@ -38,7 +38,7 @@ filterable multiple show-checkbox - value-key="id" + value-key="dataAssetCatalogAstno" placeholder="请选择关联资产" :default-expand-all="true" :render-after-expand="false" @@ -46,7 +46,7 @@ :clearable="true" :data="assetTree" :props="{ - value: 'id', + value: 'dataAssetCatalogAstno', label: 'dataAssetCatalogName', children: 'children', }" @@ -138,9 +138,11 @@ const rules = ref({ ], }) +const currentRow = ref({}) const formRef = ref(null) const openDialog = (row) => { open.value = true + currentRow.value = row setAssetTree() form.value = { contentName: undefined, @@ -167,11 +169,29 @@ const openDialog = (row) => { }) } +const filterAssetTree = (tree) => { + return tree + .map((node, index) => ({ + ...node, + dataAssetCatalogAstno: node.dataAssetCatalogAstno || index, + })) // 复制节点,避免修改原数据 + .filter((node) => { + if (node.children) { + node.children = filterAssetTree(node.children) // 递归过滤子节点 + } + return node.rel_status !== 1 || hasAsset(node.dataAssetCatalogAstno) + }) +} + +const hasAsset = (astOnum) => { + return currentRow.value.children.find((i) => i.astOnum === astOnum) +} + const addTreeNodeId = (tree) => { return tree.map((node, index) => { return { ...node, - id: node.dataAssetCatalogAstno || index, + dataAssetCatalogAstno: node.dataAssetCatalogAstno || index, children: node.children && node.children.length ? addTreeNodeId(node.children) @@ -183,7 +203,7 @@ const addTreeNodeId = (tree) => { const assetTree = ref([]) const setAssetTree = () => { getDirectoryAsset().then(({ data }) => { - assetTree.value = addTreeNodeId(data) + assetTree.value = filterAssetTree(data) }) } diff --git a/vue-fastapi-frontend/src/views/dataAsset/directory/index.vue b/vue-fastapi-frontend/src/views/dataAsset/directory/index.vue index cfdcfd5..0d12ed5 100644 --- a/vue-fastapi-frontend/src/views/dataAsset/directory/index.vue +++ b/vue-fastapi-frontend/src/views/dataAsset/directory/index.vue @@ -1,7 +1,7 @@ @@ -168,7 +234,7 @@ - + @@ -286,17 +368,21 @@ import { delDirectoryAsset, addDirectoryCollection, cancelDirectoryCollection, + getMetaSecurityData, + deleteBookmarkFolder, + getAssetFieldTable, } from '@/api/dataAsset/directory' import auth from '@/plugins/auth' import FormDialog from './components/FormDialog.vue' import MoveDialog from './components/MoveDialog.vue' import MergerDialog from './components/MergerDialog.vue' import AssetMoveDialog from './components/AssetMoveDialog.vue' -import useUserStore from '@/store/modules/user' +import BookmarkFormDialog from './components/BookmarkFormDialog.vue' +import AssetBookmarkDialog from './components/AssetBookmarkDialog.vue' +import BookmarkMoveDialog from './components/BookmarkMoveDialog.vue' import { nextTick } from 'vue' const { proxy } = getCurrentInstance() const { hasPermiOr } = auth -const userStore = useUserStore() const defaultProps = { children: 'children', @@ -345,9 +431,6 @@ setDirectoryTree().then(async () => { currentNode.value = directoryTree.value[0] directoryTableData.value = directoryTree.value[0].children || [] await setHtmlContent(currentNode.value) - setTimeout(() => { - setIframeSize() - }, 300) } }) @@ -376,22 +459,31 @@ const isRoot = (data) => { // 是否我的收藏目录 const isCollectionDirectory = (data) => { - return data.contentName === '我的收藏' + return data.contentOnum === 2 && !data.relaOnum } -// 是否收藏的目录 -const isCollection = (data) => { - return false +// 是否我的收藏子目录 +const isCollectionSubDirectory = (data) => { + return data.suprContentOnum === 2 } // 是否已收藏的 const isCollected = (data) => { return data.bookmarkFlag === 1 } - +// 是否收藏目录下的资产 +const isAssetInCollection = (data) => { + return data.sczcFlag === 1 +} // 是否子目录 const isDirectory = (data) => { - return data.contentOnum && !isRoot(data) && !data.astOnum + return ( + data.contentOnum && + !isRoot(data) && + !isCollectionDirectory(data) && + !isCollectionSubDirectory(data) && + !data.astOnum + ) } // 是否资产 @@ -400,32 +492,55 @@ const isAsset = (data) => { } const activeName = ref('1') -const handleNodeClick = async (data) => { - if (isCollectionDirectory(data)) { +const faq = ref(``) +const metaSecurityData = ref([]) +const assetFieldData = ref([]) +const tablesRowCol = ref([]) +const handleNodeClick = async (node) => { + if (isCollectionDirectory(node)) { return } + tablesRowCol.value = [] + assetFieldData.value = [] + metaSecurityData.value = [] activeName.value = '1' currentNode.value = { - ...data, + ...node, } - directoryTableData.value = data.children - if (!data.astOnum) { - await setHtmlContent(data) - setTimeout(() => { - setIframeSize() - }, 300) + directoryTableData.value = node.children + if (!node.astOnum) { + await setHtmlContent(node) + } else { + faq.value = node.dataAstFaq + getMetaSecurityData({ + dataAstSrc: node.dataAstSrc, + dataAstEngName: node.dataAstEngName, + }) + .then(({ data }) => { + metaSecurityData.value = data.data + tablesRowCol.value = data.tablesRowCol + .split(',') + .map((i) => ({ prop: i, label: '' })) + return getAssetFieldTable(node.astNo) + }) + .then(({ data }) => { + assetFieldData.value = data.columnList || [] + tablesRowCol.value = tablesRowCol.value.map((i) => { + const item = assetFieldData.value.find((j) => j.fldEngName === i.prop) + if (item) { + i.label = item.fldCnName + } + return i + }) + }) } } -const handleCollect = (data, e) => { +const assetBookmarkDialogRef = ref(null) +const handleAssetBookmarkDialogOpen = (data, e) => { e.stopPropagation() - addDirectoryCollection({ - dataAstNo: String(data.dataAstNo), - userId: String(userStore.id), - }).then(() => { - proxy.$modal.msgSuccess('收藏成功') - setDirectoryTree() - }) + assetBookmarkDialogRef.value.title = '新增收藏' + assetBookmarkDialogRef.value.openDialog(data) } const handleCollectionCancel = (data, e) => { @@ -500,6 +615,40 @@ const handleAssetMoveDialogOpen = (data) => { assetMoveDialogRef.value.openDialog(data) } +const bookmarkFormDialogRef = ref(null) +const handleBookmarkFormAddDialogOpen = (data) => { + bookmarkFormDialogRef.value.title = '新增收藏目录' + bookmarkFormDialogRef.value.openDialog() +} + +const handleBookmarkFormEditDialogOpen = (data) => { + bookmarkFormDialogRef.value.title = '修改收藏目录' + bookmarkFormDialogRef.value.openDialog(data) +} + +const handleBookmarkFolderDelete = (data) => { + ElMessageBox.confirm( + `确定删除 ${data.contentName} 目录及其收藏吗?`, + '目录删除', + { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + } + ).then(() => { + deleteBookmarkFolder(data.contentOnum).then(() => { + proxy.$modal.msgSuccess('删除成功') + setDirectoryTree() + }) + }) +} + +const bookmarkMoveDialogRef = ref(null) +const handleBookmarkMoveDialogOpen = (data) => { + bookmarkMoveDialogRef.value.title = '移动收藏' + bookmarkMoveDialogRef.value.openDialog(data) +} + const handleCommand = (command, data) => { const strategy = { handleAddDialogOpen: handleAddDialogOpen, @@ -509,12 +658,14 @@ const handleCommand = (command, data) => { handleMergerDialogOpen: handleMergerDialogOpen, handleAssetDelete: handleAssetDelete, handleAssetMoveDialogOpen: handleAssetMoveDialogOpen, + handleBookmarkFormAddDialogOpen: handleBookmarkFormAddDialogOpen, + handleBookmarkFormEditDialogOpen: handleBookmarkFormEditDialogOpen, + handleBookmarkFolderDelete: handleBookmarkFolderDelete, + handleBookmarkMoveDialogOpen: handleBookmarkMoveDialogOpen, } strategy[command](data) } -const faq = `1、常见问题1\n2、常见问题2\n3、常见问题3` - const iframeStyle = ref({ width: '100%', height: '100%', @@ -539,13 +690,17 @@ const setIframeSize = () => { content.body.clientHeight, content.documentElement.clientHeight ) - console.log('width', width) - console.log('height', height) iframeStyle.value = { width: `${width}px`, height: `${height}px`, } } + +const handleIframeLoad = () => { + nextTick(() => { + setIframeSize() + }) +} diff --git a/vue-fastapi-frontend/src/views/dataint/dataquery/index.vue b/vue-fastapi-frontend/src/views/dataint/dataquery/index.vue index 364493c..4a534d5 100644 --- a/vue-fastapi-frontend/src/views/dataint/dataquery/index.vue +++ b/vue-fastapi-frontend/src/views/dataint/dataquery/index.vue @@ -1,9 +1,206 @@ + - \ No newline at end of file +