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 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+ 重置
+
+
+
+
+
+
+ 新增
+
+
+ 修改
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ row.clasEffFlag === '1' ? '有效' : '无效' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 取消
+ 保存
+
+
+
+
+
+
+