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 eaab5d6..7365a73 100644
--- a/vue-fastapi-backend/module_admin/controller/metadata_config_controller.py
+++ b/vue-fastapi-backend/module_admin/controller/metadata_config_controller.py
@@ -22,6 +22,8 @@ from module_admin.entity.vo.metadata_config_vo import (
SecuBizPermiConfigPageQueryModel,
BatchBusiLabelConfigModel,
BatchDatatypeLabelConfigModel,
+ BatchTableRelaLabelConfigModel,
+ TableRelaLabelConfigQuery,
ColOpTypeLabelPageQueryModel,
BatchDataopLabelConfigModelVo,
BatchBusiLabelConfigPageQueryModel,
@@ -443,6 +445,18 @@ async def get_datatype_label_list(
return ResponseUtil.success(data=result)
+@metadataConfigController.get('/tableRelaLabel/list', response_model=PageResponseModel)
+async def get_tableRela_label_list(
+ request: Request,
+ query: TableRelaLabelConfigQuery = Depends(TableRelaLabelConfigQuery.as_query),
+ query_db: AsyncSession = Depends(get_db),
+
+):
+ result = await BatchLabelConfigService.get_table_rel_list_services(query_db, query, False)
+ logger.info('获取数据类型标签配置列表成功')
+ return ResponseUtil.success(data=result)
+
+
@metadataConfigController.post('/datatypeLabel')
@ValidateFields(validate_model='add_datatype_label')
async def add_datatype_label(
@@ -459,6 +473,22 @@ async def add_datatype_label(
return ResponseUtil.success(msg=result.message)
+@metadataConfigController.post('/tableRelaLabel')
+@ValidateFields(validate_model='add_datatype_label')
+async def add_table_rela_label(
+ request: Request,
+ model: BatchTableRelaLabelConfigModel,
+ query_db: AsyncSession = Depends(get_db),
+ current_user: CurrentUserModel = Depends(LoginService.get_current_user),
+):
+ model.upd_by = current_user.user.user_name
+ model.upd_time = datetime.now()
+
+ result = await BatchLabelConfigService.add_table_rela_services(query_db, model)
+ logger.info(result.message)
+ return ResponseUtil.success(msg=result.message)
+
+
@metadataConfigController.put('/datatypeLabel')
@ValidateFields(validate_model='edit_datatype_label')
async def edit_datatype_label(
@@ -475,6 +505,21 @@ async def edit_datatype_label(
return ResponseUtil.success(msg=result.message)
+@metadataConfigController.put('/tableRelaLabel')
+@ValidateFields(validate_model='edit_datatype_label')
+async def edit_table_rela_label(
+ request: Request,
+ model: BatchTableRelaLabelConfigModel,
+ query_db: AsyncSession = Depends(get_db),
+ current_user: CurrentUserModel = Depends(LoginService.get_current_user),
+):
+ model.upd_by = current_user.user.user_name
+ model.upd_time = datetime.now()
+ result = await BatchLabelConfigService.edit_table_rela_services(query_db, model)
+ logger.info(result.message)
+ return ResponseUtil.success(msg=result.message)
+
+
@metadataConfigController.delete('/datatypeLabel/{onum_list}')
async def delete_datatype_label(
request: Request,
@@ -486,6 +531,17 @@ async def delete_datatype_label(
return ResponseUtil.success(msg=result.message)
+@metadataConfigController.delete('/tableRelaLabel/{onum_list}')
+async def delete_datatype_label(
+ request: Request,
+ onum_list: str,
+ query_db: AsyncSession = Depends(get_db),
+):
+ result = await BatchLabelConfigService.delete_table_rela_services(query_db, onum_list)
+ logger.info(result.message)
+ return ResponseUtil.success(msg=result.message)
+
+
@metadataConfigController.get('/datatypeLabel/{onum}', response_model=BatchDatatypeLabelConfigModel)
async def get_datatype_label_detail(
request: Request,
diff --git a/vue-fastapi-backend/module_admin/dao/batch_label_config_dao.py b/vue-fastapi-backend/module_admin/dao/batch_label_config_dao.py
index 478b6c9..1d95dc1 100644
--- a/vue-fastapi-backend/module_admin/dao/batch_label_config_dao.py
+++ b/vue-fastapi-backend/module_admin/dao/batch_label_config_dao.py
@@ -1,7 +1,7 @@
from sqlalchemy import delete, select, update, and_
from sqlalchemy.ext.asyncio import AsyncSession
from module_admin.entity.do.metadata_config_do import BatchBusiLabelConfig, BatchDataopLabelConfig, \
- BatchDatatypeLabelConfig
+ BatchDatatypeLabelConfig, BatchTableRelaLabelConfig
from utils.page_util import PageUtil
@@ -90,6 +90,11 @@ class BatchLabelConfigDAO:
result = await db.execute(select(BatchDatatypeLabelConfig).where(BatchDatatypeLabelConfig.onum == onum))
return result.scalars().first()
+ @classmethod
+ async def get_table_rela_detail_by_id(cls, db: AsyncSession, onum: int):
+ result = await db.execute(select(BatchTableRelaLabelConfig).where(BatchTableRelaLabelConfig.onum == onum))
+ return result.scalars().first()
+
@classmethod
async def get_datatype_list(cls, db: AsyncSession, query_object, is_page: bool = False):
query = select(BatchDatatypeLabelConfig).where(
@@ -99,6 +104,16 @@ class BatchLabelConfigDAO:
return await PageUtil.paginate(db, query, query_object.page_num, query_object.page_size, is_page)
+ @classmethod
+ async def get_table_rel_list(cls, db: AsyncSession, query_object, is_page: bool = False):
+ query = select(BatchTableRelaLabelConfig).where(
+ BatchTableRelaLabelConfig.a_mdl_name.like(f'%{query_object.a_mdl_name}%') if query_object.a_mdl_name else True,
+ BatchTableRelaLabelConfig.b_mdl_name.like(f'%{query_object.b_mdl_name}%') if query_object.b_mdl_name else True,
+ BatchTableRelaLabelConfig.a_ssys_id == query_object.a_ssys_id if query_object.a_ssys_id else True,
+ BatchTableRelaLabelConfig.a_ssys_id == query_object.a_ssys_id if query_object.a_ssys_id else True,
+ ).order_by(BatchTableRelaLabelConfig.upd_time.desc())
+ return await PageUtil.paginate(db, query, query_object.page_num, query_object.page_size, is_page)
+
@classmethod
async def add_datatype(cls, db: AsyncSession, obj):
db_obj = BatchDatatypeLabelConfig(**obj.model_dump())
@@ -106,13 +121,29 @@ class BatchLabelConfigDAO:
await db.flush()
return db_obj
+ @classmethod
+ async def add_table_rela(cls, db: AsyncSession, obj):
+ db_obj = BatchTableRelaLabelConfig(**obj.model_dump())
+ db.add(db_obj)
+ await db.flush()
+ return db_obj
+
@classmethod
async def edit_datatype(cls, db: AsyncSession, onum: int, update_data: dict):
await db.execute(
update(BatchDatatypeLabelConfig).where(BatchDatatypeLabelConfig.onum == onum).values(**update_data))
+ @classmethod
+ async def edit_table_rela(cls, db: AsyncSession, onum: int, update_data: dict):
+ await db.execute(
+ update(BatchTableRelaLabelConfig).where(BatchTableRelaLabelConfig.onum == onum).values(**update_data))
+
@classmethod
async def delete_datatype(cls, db: AsyncSession, onum_list: list[int]):
await db.execute(delete(BatchDatatypeLabelConfig).where(BatchDatatypeLabelConfig.onum.in_(onum_list)))
+ @classmethod
+ async def delete_table_rela(cls, db: AsyncSession, onum_list: list[int]):
+ await db.execute(delete(BatchTableRelaLabelConfig).where(BatchTableRelaLabelConfig.onum.in_(onum_list)))
+
# endregion
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 46994ce..bc4bfd7 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
@@ -153,6 +153,23 @@ class BatchDatatypeLabelConfig(Base):
upd_time = Column(DateTime, nullable=True, comment='更新时间')
+class BatchTableRelaLabelConfig(Base):
+ """
+ 批处理字段类型标签配置表 ORM 映射类,对应表 t_batch_datatype_label_config
+ """
+ __tablename__ = "t_batch_tab_rela_label_config"
+
+ onum = Column(Integer, primary_key=True, autoincrement=True, comment="唯一编号")
+ rela_type = Column(String(100), nullable=True, comment="字段类型")
+ ratio = Column(DECIMAL(10, 4), nullable=True, comment="比率")
+ a_ssys_id = Column(Integer, nullable=True)
+ a_mdl_name = Column(String(50), nullable=True)
+ b_ssys_id = Column(Integer, nullable=True)
+ b_mdl_name = Column(String(50), nullable=True)
+ upd_by = Column(String(50), nullable=True)
+ upd_time = Column(DateTime, nullable=True, comment='更新时间')
+
+
class DatasecConfig(Base):
"""
数据安全参数配置 ORM 映射类,对应表 t_datasec_config
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 96300c9..804ce8d 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
@@ -279,6 +279,23 @@ class BatchDatatypeLabelConfigModel(BaseModel):
upd_time: Optional[datetime] = Field(default=None, description='更新时间')
+class BatchTableRelaLabelConfigModel(BaseModel):
+ """
+ 批处理字段类型标签配置 Pydantic 模型
+ """
+ model_config = ConfigDict(alias_generator=to_camel, from_attributes=True)
+
+ onum: Optional[int] = Field(default=None, description='唯一编号')
+ rela_type: Optional[str] = Field(default=None, description='字段类型')
+ ratio: Optional[float] = Field(default=None, description='比率')
+ a_ssys_id: Optional[int] = Field(default=None, description='系统代码')
+ a_mdl_name: Optional[str] = Field(default=None, description='模块名称')
+ b_ssys_id: Optional[int] = Field(default=None, description='系统代码')
+ b_mdl_name: Optional[str] = Field(default=None, description='模块名称')
+ upd_by: Optional[str] = Field(default=None, description='更新人员')
+ upd_time: Optional[datetime] = Field(default=None, description='更新时间')
+
+
class BatchDataopLabelConfigModelVo(BaseModel):
"""
批处理字段类型标签配置 Pydantic 模型
@@ -321,6 +338,17 @@ class ColOpTypeLabelPageQueryModel(BaseModel):
page_size: Optional[int] = Field(default=None, description='每页记录数')
+@as_query
+class TableRelaLabelConfigQuery(BaseModel):
+ model_config = ConfigDict(alias_generator=to_camel, from_attributes=True)
+ a_ssys_id: Optional[int] = Field(default=None, description='系统名称A')
+ a_mdl_name: Optional[str] = Field(default=None, description='模式名称A')
+ b_ssys_id: Optional[int] = Field(default=None, description='系统名称B')
+ b_mdl_name: Optional[str] = Field(default=None, description='模式名称B')
+ page_num: Optional[int] = Field(default=None, description='当前页码')
+ page_size: Optional[int] = Field(default=None, description='每页记录数')
+
+
@as_query
class BatchDatatypeLabelConfigPageQueryModel(BatchDatatypeLabelConfigModel):
page_num: int = Field(default=1, description='当前页码')
diff --git a/vue-fastapi-backend/module_admin/service/batch_label_config_service.py b/vue-fastapi-backend/module_admin/service/batch_label_config_service.py
index 322afb5..88ae108 100644
--- a/vue-fastapi-backend/module_admin/service/batch_label_config_service.py
+++ b/vue-fastapi-backend/module_admin/service/batch_label_config_service.py
@@ -147,6 +147,10 @@ class BatchLabelConfigService:
async def get_datatype_list_services(cls, db: AsyncSession, query_object, is_page: bool = False):
return await BatchLabelConfigDAO.get_datatype_list(db, query_object, is_page)
+ @classmethod
+ async def get_table_rel_list_services(cls, db: AsyncSession, query_object, is_page: bool = False):
+ return await BatchLabelConfigDAO.get_table_rel_list(db, query_object, is_page)
+
@classmethod
async def add_datatype_services(cls, db: AsyncSession, page_object):
try:
@@ -157,6 +161,16 @@ class BatchLabelConfigService:
await db.rollback()
raise e
+ @classmethod
+ async def add_table_rela_services(cls, db: AsyncSession, page_object):
+ try:
+ await BatchLabelConfigDAO.add_table_rela(db, page_object)
+ await db.commit()
+ return CrudResponseModel(is_success=True, message="新增成功")
+ except Exception as e:
+ await db.rollback()
+ raise e
+
@classmethod
async def edit_datatype_services(cls, db: AsyncSession, page_object):
edit_data = page_object.model_dump(exclude_unset=True)
@@ -172,6 +186,21 @@ class BatchLabelConfigService:
else:
raise ServiceException(message="数据类型标签配置不存在")
+ @classmethod
+ async def edit_table_rela_services(cls, db: AsyncSession, page_object):
+ edit_data = page_object.model_dump(exclude_unset=True)
+ info = await BatchLabelConfigDAO.get_table_rela_detail_by_id(db, page_object.onum)
+ if info:
+ try:
+ await BatchLabelConfigDAO.edit_table_rela(db, page_object.onum, edit_data)
+ await db.commit()
+ return CrudResponseModel(is_success=True, message="更新成功")
+ except Exception as e:
+ await db.rollback()
+ raise e
+ else:
+ raise ServiceException(message="数据类型标签配置不存在")
+
@classmethod
async def delete_datatype_services(cls, db: AsyncSession, onum_list: str):
id_list = [int(x.strip()) for x in onum_list.split(",") if x.strip()]
@@ -186,6 +215,19 @@ class BatchLabelConfigService:
await db.rollback()
raise e
+ @classmethod
+ async def delete_table_rela_services(cls, db: AsyncSession, onum_list: str):
+ id_list = [int(x.strip()) for x in onum_list.split(",") if x.strip()]
+ if not id_list:
+ raise ServiceException(message="无效的编号列表")
+ try:
+ await BatchLabelConfigDAO.delete_table_rela(db, id_list)
+ await db.commit()
+ return CrudResponseModel(is_success=True, message="删除成功")
+ except Exception as e:
+ await db.rollback()
+ raise e
+
@classmethod
async def get_datatype_detail_services(cls, db: AsyncSession, onum: str):
result = await BatchLabelConfigDAO.get_datatype_detail_by_id(db, onum)
diff --git a/vue-fastapi-backend/utils/common_util.py b/vue-fastapi-backend/utils/common_util.py
index 86f502e..68c10b7 100644
--- a/vue-fastapi-backend/utils/common_util.py
+++ b/vue-fastapi-backend/utils/common_util.py
@@ -46,7 +46,8 @@ class SqlalchemyUtil:
@classmethod
def base_to_dict(
- cls, obj: Union[Base, Dict], transform_case: Literal['no_case', 'snake_to_camel', 'camel_to_snake'] = 'no_case'
+ cls, obj: Union[Base, Dict],
+ transform_case: Literal['no_case', 'snake_to_camel', 'camel_to_snake'] = 'no_case'
):
"""
将sqlalchemy模型对象转换为字典
@@ -69,7 +70,7 @@ class SqlalchemyUtil:
@classmethod
def serialize_result(
- cls, result: Any, transform_case: Literal['no_case', 'snake_to_camel', 'camel_to_snake'] = 'no_case'
+ cls, result: Any, transform_case: Literal['no_case', 'snake_to_camel', 'camel_to_snake'] = 'no_case'
):
"""
将sqlalchemy查询结果序列化
@@ -254,6 +255,79 @@ def get_excel_template(header_list: List, selector_header_list: List, option_lis
return excel_data
+def get_excel_template_with_sheets(sheet_configs: List[Dict], # 每个Sheet的配置(包含表头、选择器等)
+ option_list: List[dict] # 全局选择器选项(所有Sheet共享)
+ ):
+ """
+ 生成多Sheet页的Excel模板(支持下拉选择器)
+
+ :param sheet_configs: 每个Sheet的配置,格式示例:
+ [
+ {
+ "sheet_name": "Sheet1", # Sheet名称
+ "header_list": ["姓名", "性别", "城市"], # 表头
+ "selector_header_list": ["性别", "城市"], # 需要下拉选择的表头
+ },
+ {
+ "sheet_name": "Sheet2",
+ "header_list": ["产品", "类别", "价格"],
+ "selector_header_list": ["类别"],
+ }
+ ]
+ :param option_list: 下拉选项配置,格式示例:
+ [
+ {"性别": ["男", "女"], "城市": ["北京", "上海"]}, # Sheet1的下拉选项
+ {"类别": ["电子产品", "食品", "服装"]} # Sheet2的下拉选项
+ ]
+ :return: Excel文件的二进制数据
+ """
+ wb = Workbook()
+ # 删除默认创建的Sheet(如果不需要)
+ if "Sheet" in wb.sheetnames:
+ wb.remove(wb["Sheet"])
+
+ # 遍历每个Sheet的配置
+ for sheet_config in sheet_configs:
+ sheet_name = sheet_config["sheet_name"]
+ header_list = sheet_config["header_list"]
+ selector_header_list = sheet_config["selector_header_list"]
+ # 创建Sheet
+ ws = wb.create_sheet(title=sheet_name)
+ # 设置表头样式
+ header_fill = PatternFill(start_color="ababab", end_color="ababab", fill_type="solid")
+ # 写入表头
+ for col_num, header in enumerate(header_list, 1):
+ cell = ws.cell(row=1, column=col_num)
+ cell.value = header
+ cell.fill = header_fill
+ cell.alignment = Alignment(horizontal="center")
+ ws.column_dimensions[get_column_letter(col_num)].width = 12
+ # 设置下拉选择器
+ for selector_header in selector_header_list:
+ if selector_header not in header_list:
+ continue # 防止配置错误
+ column_index = header_list.index(selector_header) + 1
+ column_letter = get_column_letter(column_index)
+ # 从option_list中获取当前Sheet的选项(假设option_list顺序与sheet_configs一致)
+ sheet_options = option_list[sheet_configs.index(sheet_config)]
+ selector_options = sheet_options.get(selector_header, [])
+ if selector_options:
+ dv = DataValidation(
+ type="list",
+ formula1=f'"{",".join(selector_options)}"', # 下拉选项(逗号分隔)
+ )
+ # 应用到整个列(从第2行开始)
+ dv.add(f"{column_letter}2:{column_letter}1048576")
+ ws.add_data_validation(dv)
+ # 保存为二进制数据
+ file = io.BytesIO()
+ wb.save(file)
+ file.seek(0)
+ # 读取字节数据
+ excel_data = file.getvalue()
+ return excel_data
+
+
def get_filepath_from_url(url: str):
"""
工具方法:根据请求参数获取文件路径
diff --git a/vue-fastapi-frontend/src/api/metadataConfig/metadataConfig.js b/vue-fastapi-frontend/src/api/metadataConfig/metadataConfig.js
index f2771ab..e9493b6 100644
--- a/vue-fastapi-frontend/src/api/metadataConfig/metadataConfig.js
+++ b/vue-fastapi-frontend/src/api/metadataConfig/metadataConfig.js
@@ -291,6 +291,15 @@ export function getDatatypeLabelList(data) {
})
}
+// 获取表关系属性配置列表(分页)
+export function getTableRelaLabelList(data) {
+ return request({
+ url: '/default-api/metadataConfig/tableRelaLabel/list',
+ method: 'get',
+ params: data
+ })
+}
+
// 新增数据类型标签
export function addDatatypeLabel(data) {
return request({
@@ -299,20 +308,28 @@ export function addDatatypeLabel(data) {
data
})
}
+// 新增表关系类型标签
+export function addTableRelaLabel(data) {
+ return request({
+ url: '/default-api/metadataConfig/tableRelaLabel',
+ method: 'post',
+ data
+ })
+}
// 编辑数据类型标签
-export function editDatatypeLabel(data) {
+export function editTableRelaLabel(data) {
return request({
- url: '/default-api/metadataConfig/datatypeLabel',
+ url: '/default-api/metadataConfig/tableRelaLabel',
method: 'put',
data
})
}
// 删除数据类型标签
-export function deleteDatatypeLabel(onumList) {
+export function deleteTableRelaLabel(onumList) {
return request({
- url: '/default-api/metadataConfig/datatypeLabel/' + onumList,
+ url: '/default-api/metadataConfig/tableRelaLabel/' + onumList,
method: 'delete'
})
}
diff --git a/vue-fastapi-frontend/src/views/metadataConfig/metaclas/index.vue b/vue-fastapi-frontend/src/views/metadataConfig/metaclas/index.vue
index bef108d..4d6434d 100644
--- a/vue-fastapi-frontend/src/views/metadataConfig/metaclas/index.vue
+++ b/vue-fastapi-frontend/src/views/metadataConfig/metaclas/index.vue
@@ -131,12 +131,12 @@
>
-
+
-
+
@@ -377,11 +377,12 @@ function handleSearch() {
// ===== 值类型弹窗处理 =====
function openAddDialog1() {
title.value = "新增值类型参数";
- Object.assign(form1.value, { datatype: "", ratio: null,
- ssysId: queryForm.ssysId,
- mdlName: queryForm.mdlName, });
open1.value = true;
+ form1.value = { datatype: "", ratio: null,
+ ssysId: queryForm.ssysId,
+ mdlName: queryForm.mdlName, }
}
+
function openEditDialog1(row) {
if (!row) {
ElMessage.warning("请选择一条记录进行编辑");
@@ -441,26 +442,26 @@ function handleClose1(done) {
// ===== 业务类型弹窗处理 =====
function openAddDialog2() {
title.value = "新增业务类型参数";
- Object.assign(form2.value, {
+ open2.value = true;
+ form2.value = {
regexName: "",
regexPattern: "",
ratio: null,
ssysId: queryForm.ssysId,
mdlName: queryForm.mdlName,
- });
- open2.value = true;
+ }
}
function openAddDialog3() {
title.value = "新增字段处理类型参数";
- Object.assign(form3.value, {
+ open3.value = true;
+ form3.value = {
opType: "",
colType: "",
colAttr: "",
ssysId: queryForm.ssysId,
mdlName: queryForm.mdlName,
ratio: null,
- });
- open3.value = true;
+ }
}
function openEditDialog2(row) {
@@ -576,10 +577,10 @@ function handleClose3(done) {
done();
}
-onMounted(() => {
- getList1();
- getList2();
- getList3();
+onMounted(async () => {
+ await getList1();
+ await getList2();
+ await getList3();
});