From 9ae9c5f657baaa610fa7a3b6f59fc797cf57c2e4 Mon Sep 17 00:00:00 2001 From: "si@aidatagov.com" Date: Mon, 26 May 2025 22:25:31 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=AE=89=E5=85=A8?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E4=BC=98=E5=8C=96=E5=8F=8A=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96=E9=A1=B5=E9=9D=A2=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/data_ast_content_controller.py | 3 +++ .../service/metasecurity_service.py | 3 ++- vue-fastapi-frontend/src/store/modules/user.js | 17 +++++++++-------- 3 files changed, 14 insertions(+), 9 deletions(-) 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 03fdb5c..f588f08 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 @@ -108,6 +108,9 @@ async def getMetaSercuityData( apiModel.dbRCode = dataAstSecuRequest.data_ast_src apiModel.username = user_name apiModel.password = password + apiModel.isPage = True + apiModel.pageNum = 1 + apiModel.pageSize = 10 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}") diff --git a/vue-fastapi-backend/module_admin/service/metasecurity_service.py b/vue-fastapi-backend/module_admin/service/metasecurity_service.py index cb9997d..97b20fb 100644 --- a/vue-fastapi-backend/module_admin/service/metasecurity_service.py +++ b/vue-fastapi-backend/module_admin/service/metasecurity_service.py @@ -306,8 +306,9 @@ class MetaSecurityService: # await test_connection(dbConnent) #3获取sql中涉及的表名 sqlScheamAndTable =await cls.get_tables_from_sql(page_object.sqlStr) + oldStrSql=generate_pagination_sql(page_object,dsDataResource["type"]) #4.执行原始sql - result = await cls.execute_sql(dbConnent, page_object.sqlStr,"原始") + result = await cls.execute_sql(dbConnent, oldStrSql,"原始") if 3 in role_id_list: resultDict={ "ctrlSql": page_object.sqlStr, diff --git a/vue-fastapi-frontend/src/store/modules/user.js b/vue-fastapi-frontend/src/store/modules/user.js index 5cc618c..3dbb5e7 100644 --- a/vue-fastapi-frontend/src/store/modules/user.js +++ b/vue-fastapi-frontend/src/store/modules/user.js @@ -31,14 +31,7 @@ const useUserStore = defineStore( setToken(res.token) this.token = res.token resolve() - }).catch(error => { - reject(error) - }) - }) - }, - getdsSysList(){ - return new Promise((resolve, reject) => { - datasourcetree() + datasourcetree() .then(res => { this.dsSysList = res.rows || [] // 确保为空时不报错 @@ -48,6 +41,14 @@ const useUserStore = defineStore( this.dsSysList = [] // 请求失败也清空列表,避免残留 reject(error) }) + }).catch(error => { + reject(error) + }) + }) + }, + getdsSysList(){ + return new Promise((resolve, reject) => { + }) }, // 获取用户信息 From 747a71059231304aa054641760ef9183001340eb Mon Sep 17 00:00:00 2001 From: "si@aidatagov.com" Date: Tue, 27 May 2025 00:22:12 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E8=B5=84=E4=BA=A7=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/views/dataAsset/directory/index.vue | 74 ++++++++++++------- 1 file changed, 47 insertions(+), 27 deletions(-) diff --git a/vue-fastapi-frontend/src/views/dataAsset/directory/index.vue b/vue-fastapi-frontend/src/views/dataAsset/directory/index.vue index 0d12ed5..33ea1a1 100644 --- a/vue-fastapi-frontend/src/views/dataAsset/directory/index.vue +++ b/vue-fastapi-frontend/src/views/dataAsset/directory/index.vue @@ -290,28 +290,51 @@ {{ currentNode.dataAstDesc }} - + - + - + + + + - - - + + + + + +
@@ -390,6 +413,7 @@ const defaultProps = { } const directoryTree = ref([]) const currentNode = ref({}) + const currentColumnData = ref({}); const directoryTableData = ref([]) const tableHeaderLabel = computed(() => { @@ -512,27 +536,21 @@ const handleNodeClick = async (node) => { await setHtmlContent(node) } else { faq.value = node.dataAstFaq + const fides =await getAssetFieldTable(node.astNo) + assetFieldData.value = fides.data.columnList || [] + tablesRowCol.value = assetFieldData.value.map((item) => ({ + prop: item.fldEngName, + label: item.fldCnName, + })) 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 - }) + }) + } } @@ -734,7 +752,9 @@ const handleIframeLoad = () => { .faq { white-space: pre-wrap; } - +.full-height-tabs { + height: calc(100vh - 320px); +} .html-box { :deep(.el-card__body) { overflow: auto; From 6d0e494eb9fde7334186ef67de9bfef2e22bf6ab Mon Sep 17 00:00:00 2001 From: "si@aidatagov.com" Date: Thu, 29 May 2025 01:00:00 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E5=85=83=E6=95=B0=E6=8D=AE=E6=A0=87?= =?UTF-8?q?=E7=AD=BE=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/metadata_config_controller.py | 80 +++++ .../module_admin/dao/metadata_config_dao.py | 80 +++++ .../module_admin/entity/do/meta_do.py | 1 + .../entity/do/metadata_config_do.py | 20 ++ .../entity/vo/metadata_config_vo.py | 61 ++++ .../service/metadata_config_service.py | 90 ++++++ vue-fastapi-backend/server.py | 2 + .../src/api/metadataConfig/metadataConfig.js | 44 +++ .../src/views/metadataConfig/clas/index.vue | 301 ++++++++++++++++++ 9 files changed, 679 insertions(+) create mode 100644 vue-fastapi-backend/module_admin/controller/metadata_config_controller.py create mode 100644 vue-fastapi-backend/module_admin/dao/metadata_config_dao.py create mode 100644 vue-fastapi-backend/module_admin/entity/do/metadata_config_do.py create mode 100644 vue-fastapi-backend/module_admin/entity/vo/metadata_config_vo.py create mode 100644 vue-fastapi-backend/module_admin/service/metadata_config_service.py create mode 100644 vue-fastapi-frontend/src/api/metadataConfig/metadataConfig.js create mode 100644 vue-fastapi-frontend/src/views/metadataConfig/clas/index.vue diff --git a/vue-fastapi-backend/module_admin/controller/metadata_config_controller.py b/vue-fastapi-backend/module_admin/controller/metadata_config_controller.py new file mode 100644 index 0000000..a419d07 --- /dev/null +++ b/vue-fastapi-backend/module_admin/controller/metadata_config_controller.py @@ -0,0 +1,80 @@ +from datetime import datetime +from fastapi import APIRouter, Depends, Request, Form +from pydantic_validation_decorator import ValidateFields +from sqlalchemy.ext.asyncio import AsyncSession +from module_admin.entity.vo.metadata_config_vo import MetadataClasModel, MetadataClasPageQueryModel +from module_admin.service.metadata_config_service import MetadataConfigService +from config.get_db import get_db +from utils.response_util import ResponseUtil +from utils.page_util import PageResponseModel +from utils.log_util import logger +from module_admin.service.login_service import LoginService +from module_admin.entity.vo.user_vo import CurrentUserModel + +metadataConfigController = APIRouter(prefix="/metadataConfig") + +@metadataConfigController.get("/clas/list", response_model=PageResponseModel) +async def get_metadata_clas_list( + request: Request, + query: MetadataClasPageQueryModel = Depends(MetadataClasPageQueryModel.as_query), + query_db: AsyncSession = Depends(get_db), +): + result = await MetadataConfigService.get_metadata_clas_list_services(query_db, query, is_page=True) + logger.info("获取元数据分类列表成功") + return ResponseUtil.success(model_content=result) + + +@metadataConfigController.post("/clas") +@ValidateFields(validate_model="add_metadata_clas") +async def add_metadata_clas( + request: Request, + add_clas: MetadataClasModel, + query_db: AsyncSession = Depends(get_db), + current_user: CurrentUserModel = Depends(LoginService.get_current_user), + +): + add_clas.upd_time = datetime.now() + add_clas.rec_subm_prsn = current_user.user.user_name + + # 这里没有用户信息,若需要创建人信息可自行补充 + result = await MetadataConfigService.add_metadata_clas_services(query_db, add_clas) + logger.info(result.message) + return ResponseUtil.success(msg=result.message) + + +@metadataConfigController.put("/clas") +@ValidateFields(validate_model="edit_metadata_clas") +async def edit_metadata_clas( + request: Request, + edit_clas: MetadataClasModel, + query_db: AsyncSession = Depends(get_db), + current_user: CurrentUserModel = Depends(LoginService.get_current_user), + +): + edit_clas.upd_time = datetime.now() + edit_clas.rec_subm_prsn = current_user.user.user_name + result = await MetadataConfigService.edit_metadata_clas_services(query_db, edit_clas) + logger.info(result.message) + return ResponseUtil.success(msg=result.message) + + +@metadataConfigController.delete("/clas/{clas_ids}") +async def delete_metadata_clas( + request: Request, + clas_ids: str, + query_db: AsyncSession = Depends(get_db), +): + result = await MetadataConfigService.delete_metadata_clas_services(query_db, clas_ids) + logger.info(result.message) + return ResponseUtil.success(msg=result.message) + + +@metadataConfigController.get("/clas/{clas_id}", response_model=MetadataClasModel) +async def get_metadata_clas_detail( + request: Request, + clas_id: int, + query_db: AsyncSession = Depends(get_db), +): + result = await MetadataConfigService.get_metadata_clas_detail_services(query_db, clas_id) + logger.info(f"获取元数据分类ID={clas_id}详情成功") + return ResponseUtil.success(data=result) diff --git a/vue-fastapi-backend/module_admin/dao/metadata_config_dao.py b/vue-fastapi-backend/module_admin/dao/metadata_config_dao.py new file mode 100644 index 0000000..ce16c58 --- /dev/null +++ b/vue-fastapi-backend/module_admin/dao/metadata_config_dao.py @@ -0,0 +1,80 @@ +from datetime import datetime, time +from sqlalchemy import delete, select, update +from sqlalchemy.ext.asyncio import AsyncSession +from module_admin.entity.do.meta_do import MetadataClas # ORM 类 + + +class MetadataConfigDao: + """ + 标签信息数据库操作层 + """ + + @classmethod + async def get_clas_detail_by_id(cls, db: AsyncSession, clas_id: int): + """ + 根据标签序号获取标签详细信息 + """ + result = await db.execute(select(MetadataClas).where(MetadataClas.clas_onum == clas_id)) + return result.scalars().first() + + @classmethod + async def get_clas_detail_by_info(cls, db: AsyncSession, clas): + """ + 根据标签参数获取标签信息(根据 MetadataClasModel 实例) + """ + result = await db.execute( + select(MetadataClas).where( + MetadataClas.clas_name == clas.clas_name if clas.clas_name else True, + MetadataClas.clas_eff_flag == clas.clas_eff_flag if clas.clas_eff_flag else True, + ) + ) + return result.scalars().first() + + @classmethod + async def get_metadata_clas_list(cls, db: AsyncSession, query_object, is_page: bool = False): + """ + 获取标签信息列表(支持分页) + """ + query = select(MetadataClas).where( + MetadataClas.clas_pri_clas.like(f"%{query_object.clas_pri_clas}%") if query_object.clas_pri_clas else True, + MetadataClas.clas_scd_clas.like(f"%{query_object.clas_scd_clas}%") if query_object.clas_scd_clas else True, + MetadataClas.clas_thre_clas.like(f"%{query_object.clas_thre_clas}%") if query_object.clas_thre_clas else True, + MetadataClas.clas_name.like(f"%{query_object.clas_name}%") if query_object.clas_name else True, + MetadataClas.clas_eff_flag == query_object.clas_eff_flag if query_object.clas_eff_flag else True, + MetadataClas.upd_time.between( + datetime.combine(datetime.strptime(query_object.begin_time, '%Y-%m-%d'), time(0, 0, 0)), + datetime.combine(datetime.strptime(query_object.end_time, '%Y-%m-%d'), time(23, 59, 59)), + ) + if query_object.begin_time and query_object.end_time else True, + ).order_by(MetadataClas.clas_onum).distinct() + + from utils.page_util import PageUtil + return await PageUtil.paginate(db, query, query_object.page_num, query_object.page_size, is_page) + + @classmethod + async def add_metadata_clas_dao(cls, db: AsyncSession, clas): + """ + 新增标签信息 + """ + db_clas = MetadataClas(**clas.model_dump()) + db.add(db_clas) + await db.flush() + return db_clas + + @classmethod + async def edit_metadata_clas_dao(cls, db: AsyncSession, clas_id: int, update_data: dict): + """ + 修改标签信息 + """ + await db.execute( + update(MetadataClas) + .where(MetadataClas.clas_onum == clas_id) + .values(**update_data) + ) + + @classmethod + async def delete_metadata_clas_dao(cls, db: AsyncSession, clas_onum_list: list[int]): + """ + 删除标签信息(支持批量) + """ + await db.execute(delete(MetadataClas).where(MetadataClas.clas_onum.in_(clas_onum_list))) 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 5c0658f..5a5f991 100644 --- a/vue-fastapi-backend/module_admin/entity/do/meta_do.py +++ b/vue-fastapi-backend/module_admin/entity/do/meta_do.py @@ -80,6 +80,7 @@ class MetadataClas(Base): clas_onum = Column(Integer, primary_key=True, comment='分类编号') clas_pri_clas = Column(String(50, collation='utf8_general_ci'), comment='一级分类') clas_scd_clas = Column(String(50, collation='utf8_general_ci'), comment='二级分类') + clas_tmpl = Column(String(200, collation='utf8_general_ci'), comment='标签模板') clas_thre_clas = Column(String(50, collation='utf8_general_ci'), comment='三级分类') clas_name = Column(String(255, collation='utf8_general_ci'), comment='分类名称') clas_eff_flag = Column(String(1, collation='utf8_general_ci'), default='0', comment='生效标志(0有效 1无效)') diff --git a/vue-fastapi-backend/module_admin/entity/do/metadata_config_do.py b/vue-fastapi-backend/module_admin/entity/do/metadata_config_do.py new file mode 100644 index 0000000..5d21c2f --- /dev/null +++ b/vue-fastapi-backend/module_admin/entity/do/metadata_config_do.py @@ -0,0 +1,20 @@ +from datetime import datetime +from sqlalchemy import Column, String, Integer, DateTime, TIMESTAMP, func +from config.database import Base + + +# class MetadataClas(Base): +# """ +# 标签信息表 +# """ +# __tablename__ = 't_metadata_clas' + +# clas_onum = Column(Integer, primary_key=True, default=0, comment='标签序号') +# clas_pri_clas = Column(String(50), default=None, comment='标签一级分类') +# clas_scd_clas = Column(String(50), default=None, comment='标签二级分类') +# clas_thre_clas = Column(String(50), default=None, comment='标签三级分类') +# clas_name = Column(String(200), default=None, comment='标签名称') +# clas_tmpl = Column(String(200), default=None, comment='标签模版') +# clas_eff_flag = Column(String(1), default=None, comment='标签有效标志') +# rec_subm_prsn = Column(String(64), default=None, comment='记录提交人') +# upd_time = Column(TIMESTAMP, default=func.now(), onupdate=func.now(), nullable=True, comment='更新时间') diff --git a/vue-fastapi-backend/module_admin/entity/vo/metadata_config_vo.py b/vue-fastapi-backend/module_admin/entity/vo/metadata_config_vo.py new file mode 100644 index 0000000..bcea6a1 --- /dev/null +++ b/vue-fastapi-backend/module_admin/entity/vo/metadata_config_vo.py @@ -0,0 +1,61 @@ +from datetime import datetime +from pydantic import BaseModel, ConfigDict, Field +from pydantic.alias_generators import to_camel +from pydantic_validation_decorator import NotBlank, Size +from typing import Literal, Optional +from module_admin.annotation.pydantic_annotation import as_query + + +class MetadataClasModel(BaseModel): + """ + 标签信息表对应 Pydantic 模型 + """ + + model_config = ConfigDict(alias_generator=to_camel, from_attributes=True) + + clas_onum: Optional[int] = Field(default=None, description='标签序号') + clas_pri_clas: Optional[str] = Field(default=None, description='标签一级分类') + clas_scd_clas: Optional[str] = Field(default=None, description='标签二级分类') + clas_thre_clas: Optional[str] = Field(default=None, description='标签三级分类') + clas_name: Optional[str] = Field(default=None, description='标签名称') + clas_tmpl: Optional[str] = Field(default=None, description='标签模版') + clas_eff_flag: Optional[Literal['0', '1']] = Field(default=None, description='标签有效标志') + rec_subm_prsn: Optional[str] = Field(default=None, description='记录提交人') + upd_time: Optional[datetime] = Field(default=None, description='更新时间') + + @NotBlank(field_name='clas_name', message='标签名称不能为空') + @Size(field_name='clas_name', min_length=1, max_length=200, message='标签名称长度不能超过200个字符') + def get_clas_name(self): + return self.clas_name + + def validate_fields(self): + self.get_clas_name() + + +class MetadataClasQueryModel(MetadataClasModel): + """ + 标签信息不分页查询模型 + """ + begin_time: Optional[str] = Field(default=None, description='开始时间') + end_time: Optional[str] = Field(default=None, description='结束时间') + + + +@as_query +class MetadataClasPageQueryModel(MetadataClasQueryModel): + """ + 标签信息分页查询模型 + """ + page_num: int = Field(default=1, description='当前页码') + page_size: int = Field(default=10, description='每页记录数') + + +class DeleteMetadataClasModel(BaseModel): + """ + 删除标签信息模型 + """ + + model_config = ConfigDict(alias_generator=to_camel) + + clas_onums: str = Field(description='需要删除的标签主键(多个用逗号分隔)') + diff --git a/vue-fastapi-backend/module_admin/service/metadata_config_service.py b/vue-fastapi-backend/module_admin/service/metadata_config_service.py new file mode 100644 index 0000000..f31fce9 --- /dev/null +++ b/vue-fastapi-backend/module_admin/service/metadata_config_service.py @@ -0,0 +1,90 @@ +from sqlalchemy.ext.asyncio import AsyncSession +from module_admin.dao.metadata_config_dao import MetadataConfigDao +from module_admin.entity.vo.common_vo import CrudResponseModel +from module_admin.entity.vo.metadata_config_vo import MetadataClasModel, MetadataClasPageQueryModel +from utils.common_util import CamelCaseUtil +from exceptions.exception import ServiceException + + +class MetadataConfigService: + """ + 元数据分类管理 Service + """ + + @classmethod + async def get_metadata_clas_list_services( + cls, query_db: AsyncSession, query_object: MetadataClasPageQueryModel, is_page: bool = False + ): + """ + 查询元数据分类列表 + """ + result = await MetadataConfigDao.get_metadata_clas_list(query_db, query_object, is_page) + return result + + @classmethod + async def add_metadata_clas_services( + cls, query_db: AsyncSession, page_object: MetadataClasModel + ): + """ + 新增元数据分类 + """ + try: + await MetadataConfigDao.add_metadata_clas_dao(query_db, page_object) + await query_db.commit() + return CrudResponseModel(is_success=True, message="新增成功") + except Exception as e: + await query_db.rollback() + raise e + + @classmethod + async def edit_metadata_clas_services( + cls, query_db: AsyncSession, page_object: MetadataClasModel + ): + """ + 编辑元数据分类 + """ + edit_data = page_object.model_dump(exclude_unset=True) + info = await cls.get_metadata_clas_detail_services(query_db, page_object.clas_onum) + if info.clas_onum: + try: + await MetadataConfigDao.edit_metadata_clas_dao(query_db, page_object.clas_onum, edit_data) + await query_db.commit() + return CrudResponseModel(is_success=True, message="更新成功") + except Exception as e: + await query_db.rollback() + raise e + else: + raise ServiceException(message="元数据标签不存在") + + @classmethod + async def delete_metadata_clas_services( + cls, query_db: AsyncSession, clas_ids: str + ): + """ + 删除元数据分类(支持多个ID用逗号分隔) + """ + if not clas_ids: + raise ServiceException(message="传入的分类ID为空") + + id_list = [int(id_str) for id_str in clas_ids.split(",") if id_str.isdigit()] + if not id_list: + raise ServiceException(message="无效的分类ID列表") + + try: + await MetadataConfigDao.delete_metadata_clas_dao(query_db, id_list) + await query_db.commit() + return CrudResponseModel(is_success=True, message="删除成功") + except Exception as e: + await query_db.rollback() + raise e + + @classmethod + async def get_metadata_clas_detail_services(cls, query_db: AsyncSession, clas_id: int): + """ + 查询元数据分类详情 + """ + result = await MetadataConfigDao.get_clas_detail_by_id(query_db, clas_id) + if result: + return MetadataClasModel(**CamelCaseUtil.transform_result(result)) + else: + return MetadataClasModel(**dict()) diff --git a/vue-fastapi-backend/server.py b/vue-fastapi-backend/server.py index 545e875..770dc3e 100644 --- a/vue-fastapi-backend/server.py +++ b/vue-fastapi-backend/server.py @@ -35,6 +35,7 @@ from module_admin.controller.cdplb_controller import cdplbController from module_admin.controller.sscf_controller import sscfController from module_admin.controller.vecset_controller import vecsetController from module_admin.controller.data_asset_controller import dataAssetController +from module_admin.controller.metadata_config_controller import metadataConfigController from sub_applications.handle import handle_sub_applications from utils.common_util import worship from utils.log_util import logger @@ -103,6 +104,7 @@ controller_list = [ {'router': sscfController, 'tags': ['智能数据-短句配置']}, {'router': vecsetController, 'tags': ['智能数据-全句配置']}, {'router': dataAssetController, 'tags': ['系统管理-数据资产详情']}, + {'router': metadataConfigController, 'tags': ['元数据管理-元数据配置管理']}, ] for controller in controller_list: diff --git a/vue-fastapi-frontend/src/api/metadataConfig/metadataConfig.js b/vue-fastapi-frontend/src/api/metadataConfig/metadataConfig.js new file mode 100644 index 0000000..42ceb64 --- /dev/null +++ b/vue-fastapi-frontend/src/api/metadataConfig/metadataConfig.js @@ -0,0 +1,44 @@ +import request from '@/utils/request' + +// 查询元数据分类列表,带分页 +export function listMetadataClas(query) { + return request({ + url: '/default-api/metadataConfig/clas/list', + method: 'get', + params: query + }) +} + +// 查询元数据分类详情 +export function getMetadataClas(clasId) { + return request({ + url: '/default-api/metadataConfig/clas/' + clasId, + method: 'get' + }) +} + +// 新增元数据分类 +export function addMetadataClas(data) { + return request({ + url: '/default-api/metadataConfig/clas', + method: 'post', + data: data + }) +} + +// 修改元数据分类 +export function updateMetadataClas(data) { + return request({ + url: '/default-api/metadataConfig/clas', + method: 'put', + data: data + }) +} + +// 删除元数据分类(支持批量,逗号分隔) +export function delMetadataClas(clasIds) { + return request({ + url: '/default-api/metadataConfig/clas/' + clasIds, + method: 'delete' + }) +} diff --git a/vue-fastapi-frontend/src/views/metadataConfig/clas/index.vue b/vue-fastapi-frontend/src/views/metadataConfig/clas/index.vue new file mode 100644 index 0000000..bb8afeb --- /dev/null +++ b/vue-fastapi-frontend/src/views/metadataConfig/clas/index.vue @@ -0,0 +1,301 @@ + + + + From 71eff27715b719fd7cf8e55dcf4e90c6b2f09867 Mon Sep 17 00:00:00 2001 From: "si@aidatagov.com" Date: Fri, 30 May 2025 01:08:54 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E5=AE=89=E5=85=A8=E7=AD=89=E7=BA=A7?= =?UTF-8?q?=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/metadata_config_controller.py | 67 +++- .../module_admin/dao/metadata_config_dao.py | 36 +++ .../entity/do/metadata_config_do.py | 13 + .../entity/vo/metadata_config_vo.py | 45 +++ .../service/metadata_config_service.py | 76 ++++- .../src/api/metadataConfig/metadataConfig.js | 44 +++ .../src/views/metadataConfig/sec/index.vue | 293 ++++++++++++++++++ 7 files changed, 571 insertions(+), 3 deletions(-) create mode 100644 vue-fastapi-frontend/src/views/metadataConfig/sec/index.vue diff --git a/vue-fastapi-backend/module_admin/controller/metadata_config_controller.py b/vue-fastapi-backend/module_admin/controller/metadata_config_controller.py index a419d07..8198c75 100644 --- a/vue-fastapi-backend/module_admin/controller/metadata_config_controller.py +++ b/vue-fastapi-backend/module_admin/controller/metadata_config_controller.py @@ -2,7 +2,7 @@ from datetime import datetime from fastapi import APIRouter, Depends, Request, Form from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession -from module_admin.entity.vo.metadata_config_vo import MetadataClasModel, MetadataClasPageQueryModel +from module_admin.entity.vo.metadata_config_vo import MetadataClasModel, MetadataClasPageQueryModel,MetadataSecModel,MetadataSecPageQueryModel from module_admin.service.metadata_config_service import MetadataConfigService from config.get_db import get_db from utils.response_util import ResponseUtil @@ -78,3 +78,68 @@ async def get_metadata_clas_detail( result = await MetadataConfigService.get_metadata_clas_detail_services(query_db, clas_id) logger.info(f"获取元数据分类ID={clas_id}详情成功") return ResponseUtil.success(data=result) +# ------------------------ MetadataSec 控制接口 ------------------------ # + +@metadataConfigController.get("/sec/list", response_model=PageResponseModel) +async def get_metadata_sec_list( + request: Request, + query: MetadataSecPageQueryModel = Depends(MetadataSecPageQueryModel.as_query), + query_db: AsyncSession = Depends(get_db), +): + result = await MetadataConfigService.get_metadata_sec_list_services(query_db, query, is_page=True) + logger.info("获取数据安全配置列表成功") + return ResponseUtil.success(model_content=result) + + +@metadataConfigController.post("/sec") +@ValidateFields(validate_model="add_metadata_sec") +async def add_metadata_sec( + request: Request, + add_sec: MetadataSecModel, + query_db: AsyncSession = Depends(get_db), + current_user: CurrentUserModel = Depends(LoginService.get_current_user), +): + add_sec.upd_time = datetime.now() + add_sec.rec_subm_prsn = current_user.user.user_name + + result = await MetadataConfigService.add_metadata_sec_services(query_db, add_sec) + logger.info(result.message) + return ResponseUtil.success(msg=result.message) + + +@metadataConfigController.put("/sec") +@ValidateFields(validate_model="edit_metadata_sec") +async def edit_metadata_sec( + request: Request, + edit_sec: MetadataSecModel, + query_db: AsyncSession = Depends(get_db), + current_user: CurrentUserModel = Depends(LoginService.get_current_user), +): + edit_sec.upd_time = datetime.now() + edit_sec.rec_subm_prsn = current_user.user.user_name + + result = await MetadataConfigService.edit_metadata_sec_services(query_db, edit_sec) + logger.info(result.message) + return ResponseUtil.success(msg=result.message) + + +@metadataConfigController.delete("/sec/{sec_ids}") +async def delete_metadata_sec( + request: Request, + sec_ids: str, + query_db: AsyncSession = Depends(get_db), +): + result = await MetadataConfigService.delete_metadata_sec_services(query_db, sec_ids) + logger.info(result.message) + return ResponseUtil.success(msg=result.message) + + +@metadataConfigController.get("/sec/{sec_id}", response_model=MetadataSecModel) +async def get_metadata_sec_detail( + request: Request, + sec_id: str, + query_db: AsyncSession = Depends(get_db), +): + result = await MetadataConfigService.get_metadata_sec_detail_services(query_db, sec_id) + logger.info(f"获取数据安全配置 onum={sec_id} 详情成功") + return ResponseUtil.success(data=result) \ No newline at end of file diff --git a/vue-fastapi-backend/module_admin/dao/metadata_config_dao.py b/vue-fastapi-backend/module_admin/dao/metadata_config_dao.py index ce16c58..282f5b0 100644 --- a/vue-fastapi-backend/module_admin/dao/metadata_config_dao.py +++ b/vue-fastapi-backend/module_admin/dao/metadata_config_dao.py @@ -2,6 +2,7 @@ from datetime import datetime, time from sqlalchemy import delete, select, update from sqlalchemy.ext.asyncio import AsyncSession from module_admin.entity.do.meta_do import MetadataClas # ORM 类 +from module_admin.entity.do.metadata_config_do import MetadataSec # ORM 类 class MetadataConfigDao: @@ -78,3 +79,38 @@ class MetadataConfigDao: 删除标签信息(支持批量) """ await db.execute(delete(MetadataClas).where(MetadataClas.clas_onum.in_(clas_onum_list))) + @classmethod + async def get_sec_detail_by_id(cls, db: AsyncSession, onum: str): + result = await db.execute(select(MetadataSec).where(MetadataSec.onum == onum)) + return result.scalars().first() + + @classmethod + async def get_metadata_sec_list(cls, db: AsyncSession, query_object, is_page: bool = False): + query = select(MetadataSec).where( + MetadataSec.sec_level_name.like(f"%{query_object.sec_level_name}%") if query_object.sec_level_name else True, + MetadataSec.sec_eff_flag == query_object.sec_eff_flag if query_object.sec_eff_flag else True, + MetadataSec.upd_time.between( + datetime.combine(datetime.strptime(query_object.begin_time, '%Y-%m-%d'), time(0, 0, 0)), + datetime.combine(datetime.strptime(query_object.end_time, '%Y-%m-%d'), time(23, 59, 59)), + ) if query_object.begin_time and query_object.end_time else True, + ).order_by(MetadataSec.upd_time.desc()).distinct() + + from utils.page_util import PageUtil + return await PageUtil.paginate(db, query, query_object.page_num, query_object.page_size, is_page) + + @classmethod + async def add_metadata_sec_dao(cls, db: AsyncSession, sec): + db_sec = MetadataSec(**sec.model_dump()) + db.add(db_sec) + await db.flush() + return db_sec + + @classmethod + async def edit_metadata_sec_dao(cls, db: AsyncSession, onum: str, update_data: dict): + await db.execute( + update(MetadataSec).where(MetadataSec.onum == onum).values(**update_data) + ) + + @classmethod + async def delete_metadata_sec_dao(cls, db: AsyncSession, onum_list: list[str]): + await db.execute(delete(MetadataSec).where(MetadataSec.onum.in_(onum_list))) \ No newline at end of file diff --git a/vue-fastapi-backend/module_admin/entity/do/metadata_config_do.py b/vue-fastapi-backend/module_admin/entity/do/metadata_config_do.py index 5d21c2f..23c6a56 100644 --- a/vue-fastapi-backend/module_admin/entity/do/metadata_config_do.py +++ b/vue-fastapi-backend/module_admin/entity/do/metadata_config_do.py @@ -18,3 +18,16 @@ from config.database import Base # clas_eff_flag = Column(String(1), default=None, comment='标签有效标志') # rec_subm_prsn = Column(String(64), default=None, comment='记录提交人') # upd_time = Column(TIMESTAMP, default=func.now(), onupdate=func.now(), nullable=True, comment='更新时间') +class MetadataSec(Base): + """ + 数据安全配置表 + """ + __tablename__ = 't_metadata_sec' + + onum = Column(String(36), primary_key=True, comment='唯一编号') + sec_eff_flag = Column(String(1), default=None, comment='有效标志') + rec_subm_prsn = Column(String(64), default=None, comment='记录提交人') + upd_time = Column(TIMESTAMP, default=func.now(), onupdate=func.now(), nullable=True, comment='更新时间') + sec_level_name = Column(String(50), default=None, comment='等级名称') + sec_level_desc = Column(String(200), default=None, comment='等级说明') + sec_level_summary = Column(String(200), comment='等级简介') \ No newline at end of file diff --git a/vue-fastapi-backend/module_admin/entity/vo/metadata_config_vo.py b/vue-fastapi-backend/module_admin/entity/vo/metadata_config_vo.py index bcea6a1..fa17988 100644 --- a/vue-fastapi-backend/module_admin/entity/vo/metadata_config_vo.py +++ b/vue-fastapi-backend/module_admin/entity/vo/metadata_config_vo.py @@ -59,3 +59,48 @@ class DeleteMetadataClasModel(BaseModel): clas_onums: str = Field(description='需要删除的标签主键(多个用逗号分隔)') +class MetadataSecModel(BaseModel): + """ + 数据安全配置表对应 Pydantic 模型 + """ + + model_config = ConfigDict(alias_generator=to_camel, from_attributes=True) + + onum: Optional[str] = Field(default=None, description='唯一编号') + sec_eff_flag: Optional[Literal['0', '1']] = Field(default=None, description='有效标志') + rec_subm_prsn: Optional[str] = Field(default=None, description='记录提交人') + upd_time: Optional[datetime] = Field(default=None, description='更新时间') + sec_level_name: Optional[str] = Field(default=None, description='等级名称') + sec_level_desc: Optional[str] = Field(default=None, description='等级说明') + sec_level_summary: Optional[str] = Field(default=None, description='等级简介') + + @NotBlank(field_name='sec_level_name', message='等级名称不能为空') + @Size(field_name='sec_level_name', min_length=1, max_length=50, message='等级名称长度不能超过50个字符') + def get_sec_level_name(self): + return self.sec_level_name + + def validate_fields(self): + self.get_sec_level_name() +class DeleteMetadataSecModel(BaseModel): + """ + 删除数据安全配置模型 + """ + + model_config = ConfigDict(alias_generator=to_camel) + + onums: str = Field(description='需要删除的唯一编号(多个用逗号分隔)') +class MetadataSecQueryModel(MetadataSecModel): + """ + 数据安全配置不分页查询模型 + """ + begin_time: Optional[str] = Field(default=None, description='开始时间') + end_time: Optional[str] = Field(default=None, description='结束时间') + +@as_query +class MetadataSecPageQueryModel(MetadataSecQueryModel): + """ + 数据安全配置分页查询模型 + """ + page_num: int = Field(default=1, description='当前页码') + page_size: int = Field(default=10, description='每页记录数') + \ No newline at end of file diff --git a/vue-fastapi-backend/module_admin/service/metadata_config_service.py b/vue-fastapi-backend/module_admin/service/metadata_config_service.py index f31fce9..62a0ec4 100644 --- a/vue-fastapi-backend/module_admin/service/metadata_config_service.py +++ b/vue-fastapi-backend/module_admin/service/metadata_config_service.py @@ -1,10 +1,10 @@ from sqlalchemy.ext.asyncio import AsyncSession from module_admin.dao.metadata_config_dao import MetadataConfigDao from module_admin.entity.vo.common_vo import CrudResponseModel -from module_admin.entity.vo.metadata_config_vo import MetadataClasModel, MetadataClasPageQueryModel +from module_admin.entity.vo.metadata_config_vo import MetadataClasModel, MetadataClasPageQueryModel,MetadataSecModel,MetadataSecPageQueryModel from utils.common_util import CamelCaseUtil from exceptions.exception import ServiceException - +import uuid class MetadataConfigService: """ @@ -88,3 +88,75 @@ class MetadataConfigService: return MetadataClasModel(**CamelCaseUtil.transform_result(result)) else: return MetadataClasModel(**dict()) + @classmethod + async def get_metadata_sec_list_services( + cls, query_db: AsyncSession, query_object: MetadataSecPageQueryModel, is_page: bool = False + ): + """ + 查询数据安全配置列表 + """ + result = await MetadataConfigDao.get_metadata_sec_list(query_db, query_object, is_page) + return result + + @classmethod + async def add_metadata_sec_services(cls, query_db: AsyncSession, page_object: MetadataSecModel): + """ + 新增数据安全配置 + """ + try: + page_object.onum=str(uuid.uuid4()) + await MetadataConfigDao.add_metadata_sec_dao(query_db, page_object) + await query_db.commit() + return CrudResponseModel(is_success=True, message="新增成功") + except Exception as e: + await query_db.rollback() + raise e + + @classmethod + async def edit_metadata_sec_services(cls, query_db: AsyncSession, page_object: MetadataSecModel): + """ + 编辑数据安全配置 + """ + edit_data = page_object.model_dump(exclude_unset=True) + info = await cls.get_metadata_sec_detail_services(query_db, page_object.onum) + if info.onum: + try: + await MetadataConfigDao.edit_metadata_sec_dao(query_db, page_object.onum, edit_data) + await query_db.commit() + return CrudResponseModel(is_success=True, message="更新成功") + except Exception as e: + await query_db.rollback() + raise e + else: + raise ServiceException(message="数据安全配置不存在") + + @classmethod + async def delete_metadata_sec_services(cls, query_db: AsyncSession, onum_list: str): + """ + 删除数据安全配置(支持多个编号用逗号分隔) + """ + if not onum_list: + raise ServiceException(message="传入的编号为空") + + id_list = [onum.strip() for onum in onum_list.split(",") if onum.strip()] + if not id_list: + raise ServiceException(message="无效的编号列表") + + try: + await MetadataConfigDao.delete_metadata_sec_dao(query_db, id_list) + await query_db.commit() + return CrudResponseModel(is_success=True, message="删除成功") + except Exception as e: + await query_db.rollback() + raise e + + @classmethod + async def get_metadata_sec_detail_services(cls, query_db: AsyncSession, onum: str): + """ + 查询数据安全配置详情 + """ + result = await MetadataConfigDao.get_sec_detail_by_id(query_db, onum) + if result: + return MetadataSecModel(**CamelCaseUtil.transform_result(result)) + else: + return MetadataSecModel(**dict()) \ No newline at end of file diff --git a/vue-fastapi-frontend/src/api/metadataConfig/metadataConfig.js b/vue-fastapi-frontend/src/api/metadataConfig/metadataConfig.js index 42ceb64..0491c4a 100644 --- a/vue-fastapi-frontend/src/api/metadataConfig/metadataConfig.js +++ b/vue-fastapi-frontend/src/api/metadataConfig/metadataConfig.js @@ -42,3 +42,47 @@ export function delMetadataClas(clasIds) { method: 'delete' }) } +// ========================== MetadataSec 接口(新增) ========================== + +// 查询数据安全配置列表,带分页 +export function listMetadataSec(query) { + return request({ + url: '/default-api/metadataConfig/sec/list', + method: 'get', + params: query + }) +} + +// 查询数据安全配置详情 +export function getMetadataSec(secId) { + return request({ + url: '/default-api/metadataConfig/sec/' + secId, + method: 'get' + }) +} + +// 新增数据安全配置 +export function addMetadataSec(data) { + return request({ + url: '/default-api/metadataConfig/sec', + method: 'post', + data: data + }) +} + +// 修改数据安全配置 +export function updateMetadataSec(data) { + return request({ + url: '/default-api/metadataConfig/sec', + method: 'put', + data: data + }) +} + +// 删除数据安全配置(支持批量,逗号分隔) +export function delMetadataSec(secIds) { + return request({ + url: '/default-api/metadataConfig/sec/' + secIds, + method: 'delete' + }) +} \ No newline at end of file diff --git a/vue-fastapi-frontend/src/views/metadataConfig/sec/index.vue b/vue-fastapi-frontend/src/views/metadataConfig/sec/index.vue new file mode 100644 index 0000000..d5be39a --- /dev/null +++ b/vue-fastapi-frontend/src/views/metadataConfig/sec/index.vue @@ -0,0 +1,293 @@ + + + + +