Browse Source

标签分类

master
si@aidatagov.com 2 months ago
parent
commit
4b85c1a8d0
  1. 148
      vue-fastapi-backend/module_admin/controller/metadata_config_controller.py
  2. 391
      vue-fastapi-backend/module_admin/dao/metadata_config_dao.py
  3. 7
      vue-fastapi-backend/module_admin/entity/do/meta_do.py
  4. 36
      vue-fastapi-backend/module_admin/entity/do/metadata_config_do.py
  5. 5
      vue-fastapi-backend/module_admin/entity/vo/metadata_config_vo.py
  6. 292
      vue-fastapi-backend/module_admin/service/metadata_config_service.py
  7. 92
      vue-fastapi-frontend/src/api/metadataConfig/directory.js
  8. 171
      vue-fastapi-frontend/src/views/metadataConfig/clas/components/AssetMoveDialog.vue
  9. 193
      vue-fastapi-frontend/src/views/metadataConfig/clas/components/FormDialog.vue
  10. 175
      vue-fastapi-frontend/src/views/metadataConfig/clas/components/MergerDialog.vue
  11. 173
      vue-fastapi-frontend/src/views/metadataConfig/clas/components/MoveDialog.vue
  12. 452
      vue-fastapi-frontend/src/views/metadataConfig/clas/index.vue

148
vue-fastapi-backend/module_admin/controller/metadata_config_controller.py

@ -2,6 +2,12 @@ from datetime import datetime
from fastapi import APIRouter, Depends, Request, Form from fastapi import APIRouter, Depends, Request, Form
from pydantic_validation_decorator import ValidateFields from pydantic_validation_decorator import ValidateFields
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
from module_admin.entity.vo.data_ast_content_vo import DataCatalogPageQueryModel, DeleteDataCatalogModel, \
DataCatalogResponseWithChildren, DataAssetCatalogTreeResponse, DataCatalogMovedRequest, DataCatalogMergeRequest, \
DataCatalogChild, DataCatalogMoverelRequest
from utils.log_util import logger
from config.enums import BusinessType
from module_admin.annotation.log_annotation import Log
from module_admin.entity.vo.metadata_config_vo import ( from module_admin.entity.vo.metadata_config_vo import (
MetadataClasModel, MetadataClasModel,
MetadataClasPageQueryModel, MetadataClasPageQueryModel,
@ -745,3 +751,145 @@ async def task_biz_DS_meta_metatask_delete(
edit_config_result = await MetadataConfigService.ds_metatask_delete(request, query_db, process, current_user) edit_config_result = await MetadataConfigService.ds_metatask_delete(request, query_db, process, current_user)
return ResponseUtil.success(msg=edit_config_result) return ResponseUtil.success(msg=edit_config_result)
# --------------------------------------------------------------------------------标签树---------------------------------------------------
@metadataConfigController.get(
'/cata/list', response_model=PageResponseModel)
async def get_data_catalog_list(
request: Request,
catalog_page_query: DataCatalogPageQueryModel = Depends(DataCatalogPageQueryModel.as_query),
query_db: AsyncSession = Depends(get_db),
current_user: CurrentUserModel = Depends(LoginService.get_current_user),
):
# 设置字段
user_id = current_user.user.user_id
# 获取分页数据
catalog_page_query_result = await MetadataConfigService.get_catalog_list_services(query_db, catalog_page_query, user_id,
is_page=True)
logger.info('获取成功')
return ResponseUtil.success(model_content=catalog_page_query_result)
@metadataConfigController.delete('/cata/{content_onums}',
)
@Log(title='标准分类管理', business_type=BusinessType.DELETE)
async def delete_data_catalog(request: Request, content_onums: str, query_db: AsyncSession = Depends(get_db),
current_user: CurrentUserModel = Depends(LoginService.get_current_user),
):
delete_catalog = DeleteDataCatalogModel(content_onums=content_onums)
delete_catalog_result = await MetadataConfigService.delete_catalog_services(query_db, delete_catalog,
user_id=current_user.user.user_id)
logger.info(delete_catalog_result.message)
return ResponseUtil.success(msg=delete_catalog_result.message)
@metadataConfigController.put('/cata/removerel')
@ValidateFields(validate_model='removerel_data_ast_catalog')
@Log(title='标准分类管理', business_type=BusinessType.UPDATE)
async def removerel_data_ast_catalog(
request: Request,
removerel_catalog: DataCatalogChild,
query_db: AsyncSession = Depends(get_db),
current_user: CurrentUserModel = Depends(LoginService.get_current_user),
):
# 调用服务层方法
removerel_result = await MetadataConfigService.removerel_data_ast_catalog_services(query_db, removerel_catalog)
logger.info(removerel_result.message)
# 返回标准化响应
return ResponseUtil.success()
@metadataConfigController.put('/cata/moved')
@ValidateFields(validate_model='moved_data_catalog')
@Log(title='标准分类管理', business_type=BusinessType.UPDATE)
async def moved_data_catalog(
request: Request,
moved_catalog: DataCatalogMovedRequest,
query_db: AsyncSession = Depends(get_db),
current_user: CurrentUserModel = Depends(LoginService.get_current_user),
):
# 调用服务层方法
moved_result = await MetadataConfigService.moved_catalog_instr_services(query_db, moved_catalog)
logger.info(moved_result.message)
# 返回标准化响应
return ResponseUtil.success(
msg=moved_result.message
)
@metadataConfigController.put('/cata/merge')
@ValidateFields(validate_model='merge_data_catalog')
@Log(title='标准分类管理', business_type=BusinessType.UPDATE)
async def moved_data_catalog(
request: Request,
merge_catalog: DataCatalogMergeRequest,
query_db: AsyncSession = Depends(get_db),
current_user: CurrentUserModel = Depends(LoginService.get_current_user),
):
# 调用服务层方法
merge_result = await MetadataConfigService.merge_catalog_instr_services(query_db, merge_catalog)
logger.info(merge_result.message)
# 返回标准化响应
return ResponseUtil.success(
msg=merge_result.message
)
@metadataConfigController.put('/cata/moverel')
@ValidateFields(validate_model='moverel_data_ast_catalog')
@Log(title='标准分类管理', business_type=BusinessType.UPDATE)
async def moverel_data_ast_catalog(
request: Request,
moverel_catalog: DataCatalogMoverelRequest,
query_db: AsyncSession = Depends(get_db),
current_user: CurrentUserModel = Depends(LoginService.get_current_user),
):
# 调用服务层方法
moverel_result = await MetadataConfigService.moverel_data_ast_catalog_services(query_db, moverel_catalog)
logger.info(moverel_result.message)
# 返回标准化响应
return ResponseUtil.success()
@metadataConfigController.put('/cata/edit')
@ValidateFields(validate_model='edit_data_catalog')
@Log(title='标准分类管理', business_type=BusinessType.UPDATE)
async def edit_data_catalog(
request: Request,
edit_catalog: DataCatalogResponseWithChildren,
query_db: AsyncSession = Depends(get_db),
current_user: CurrentUserModel = Depends(LoginService.get_current_user),
):
# 设置审计字段
edit_catalog.upd_prsn = current_user.user.user_name
# 调用服务层方法
edit_result = await MetadataConfigService.edit_catalog_child_services(query_db, edit_catalog)
logger.info(edit_result.message)
# 返回标准化响应
return ResponseUtil.success(
msg=edit_result.message
)
@metadataConfigController.post('/cata')
@ValidateFields(validate_model='add_data_catalog')
@Log(title='标准分类管理', business_type=BusinessType.INSERT)
async def add_data_catalog(
request: Request,
add_catalog: DataCatalogResponseWithChildren,
query_db: AsyncSession = Depends(get_db),
current_user: CurrentUserModel = Depends(LoginService.get_current_user),
):
# 设置字段
add_catalog.upd_prsn = current_user.user.user_name
# 调用服务层方法
add_result = await MetadataConfigService.add_catalog_services(query_db, add_catalog)
logger.info(add_result.message)
# 新增成功后,更新新增数据目录的父亲节点的叶子标志为0
if add_result.is_success:
if add_catalog.supr_content_onum is not None:
supr_content_onum = add_catalog.supr_content_onum
await MetadataConfigService.edit_catalog_leaf_services(query_db, supr_content_onum, 0)
else:
logger.error(add_result.message)
# 返回标准化响应
return ResponseUtil.success(
msg=add_result.message
)

391
vue-fastapi-backend/module_admin/dao/metadata_config_dao.py

@ -1,5 +1,4 @@
from datetime import datetime, time from datetime import datetime, time
from sqlalchemy import delete, select, update, and_
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
from module_admin.entity.do.meta_do import MetadataClas, MetadataExtractInfo # ORM 类 from module_admin.entity.do.meta_do import MetadataClas, MetadataExtractInfo # ORM 类
from module_admin.entity.do.metadata_config_do import MetadataSec, SecuBizConfig, SecuBizPermiConfig, SecuBizConfigRela, \ from module_admin.entity.do.metadata_config_do import MetadataSec, SecuBizConfig, SecuBizPermiConfig, SecuBizConfigRela, \
@ -7,11 +6,14 @@ from module_admin.entity.do.metadata_config_do import MetadataSec, SecuBizConfig
TaskBizConfigRela, TaskBizConfig TaskBizConfigRela, TaskBizConfig
# ORM 类 # ORM 类
from typing import List from typing import List
from module_admin.entity.do.metadata_config_do import DataAstContent, DataAstContentRela
from sqlalchemy.orm import aliased
from sqlalchemy.orm import joinedload from sqlalchemy.orm import joinedload
from sqlalchemy.sql import true from sqlalchemy.sql import true
from utils.page_util import PageUtil from utils.page_util import PageUtil
from module_admin.entity.vo.data_ast_content_vo import DataCatalogPageQueryModel, DeleteDataCatalogModel, \
DataCatalogChild
from sqlalchemy import delete, select, update, desc, or_, not_, and_
class MetadataConfigDao: class MetadataConfigDao:
""" """
@ -56,10 +58,7 @@ class MetadataConfigDao:
获取标签信息列表支持分页 获取标签信息列表支持分页
""" """
query = select(MetadataClas).where( query = select(MetadataClas).where(
MetadataClas.clas_pri_clas.like(f"%{query_object.clas_pri_clas}%") if query_object.clas_pri_clas else True, MetadataClas.belt_batch_content==query_object.belt_batch_content if query_object.belt_batch_content 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_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.clas_eff_flag == query_object.clas_eff_flag if query_object.clas_eff_flag else True,
MetadataClas.upd_time.between( MetadataClas.upd_time.between(
@ -422,3 +421,381 @@ class MetadataConfigDao:
.where(TaskBizConfigRela.biz_onum == biz_onum) .where(TaskBizConfigRela.biz_onum == biz_onum)
) )
return result.scalars().all() return result.scalars().all()
# 数据标准目录
@classmethod
async def get_catalog_by_id(cls, db: AsyncSession, content_onum: int):
"""
根据目录ID获取目录详细信息
:param db: orm对象
:param content_onum: 目录ID
:return: 目录信息对象
"""
catalog_info = (
(await db.execute(select(DataAstContent).where(DataAstContent.content_onum == content_onum,
DataAstContent.content_stat == 1)))
.scalars()
.first()
)
return catalog_info
@classmethod
async def get_catalog_detail_by_info(cls, db: AsyncSession, catalog: DataCatalogPageQueryModel):
"""
根据目录参数获取目录信息
:param db: orm对象
:param catalog: 目录参数对象
:return: 目录信息对象
"""
catalog_info = (
(
await db.execute(
select(DataAstContent).where(
DataAstContent.content_name == catalog.content_name if catalog.content_name else True,
DataAstContent.content_stat == catalog.content_stat if catalog.content_stat else True,
DataAstContent.content_pic == catalog.content_pic if catalog.content_pic else True,
DataAstContent.content_stat == 1,
)
)
)
.scalars()
.first()
)
return catalog_info
@classmethod
async def update_leaf_node_flag(cls, db: AsyncSession):
"""
更新leaf_node_flag字段
"""
# 创建别名对象
t2 = aliased(DataAstContent, name='t2') # 正确使用aliased创建别名
subquery = (
select(DataAstContent.content_onum)
.where(
DataAstContent.content_stat == '1',
DataAstContent.leaf_node_flag == 0,
not_(
select(1)
.select_from(t2) # 使用别名后的表
.where(
t2.supr_content_onum == DataAstContent.content_onum,
t2.content_stat == '1'
)
.exists() # 添加exists()方法
)
)
).alias('temp')
stmt = (
update(DataAstContent)
.where(DataAstContent.content_onum.in_(subquery))
.values(leaf_node_flag=1, upd_time=datetime.now())
)
await db.execute(stmt)
@classmethod
async def add_catalog_dao(cls, db: AsyncSession, catalog1: dict, catalog2: dict):
"""
新增目录数据库操作
:param db: orm对象
:param catalog: 目录对象
:return:
"""
db_catalog = DataAstContent(**catalog1)
db.add(db_catalog)
await db.flush()
# 处理子关系(统一转换为 ORM 模型)
for child in catalog2.get('children', []):
# 如果是 Pydantic 模型实例,先转换为字典
if isinstance(child, DataCatalogChild):
child_dict = child.model_dump()
elif isinstance(child, dict):
child_dict = child
else:
raise TypeError("不支持的子关系数据类型")
# 创建 ORM 模型实例
processed_child = dict(child_dict)
processed_child['content_onum'] = db_catalog.content_onum
db_child = DataAstContentRela(**processed_child)
db.add(db_child)
await db.flush()
return db_catalog
@classmethod
async def edit_catalog_leaf_dao(cls, db: AsyncSession, catalog: dict):
"""
编辑叶子节点目录数据库操作
:param db: orm对象
:param catalog: 需要更新的目录字典
:return:
"""
content_onum = catalog['content_onum']
stmt = (
update(DataAstContent)
.where(DataAstContent.content_onum == content_onum)
.values(
leaf_node_flag=catalog['leaf_node_flag']
)
)
await db.execute(stmt)
@classmethod
async def edit_catalog_child_dao(cls, db: AsyncSession, catalog: dict):
"""
编辑目录数据库操作
:param db: orm对象
:param catalog: 需要更新的目录字典
:return:
"""
content_onum = catalog['content_onum']
stmt = (
update(DataAstContent)
.where(DataAstContent.content_onum == content_onum)
.values(
content_name=catalog['content_name'],
content_stat=catalog['content_stat'],
content_intr=catalog['content_intr'],
content_pic=catalog['content_pic'],
supr_content_onum=catalog['supr_content_onum'],
leaf_node_flag=catalog['leaf_node_flag'],
upd_prsn=catalog['upd_prsn'],
upd_time=datetime.now()
))
await db.execute(stmt)
# 处理子关系
for child in catalog.get('children', []):
rela_onum = child.get('rela_onum')
if rela_onum:
st = (
update(DataAstContentRela)
.where(DataAstContentRela.rela_onum == rela_onum)
.values(
content_onum=child.get('content_onum'),
ast_onum=child.get('ast_onum'),
rela_type=child.get('rela_type'),
rela_eff_begn_date=child.get('rela_eff_begn_date'),
rela_eff_end_date=child.get('rela_eff_end_date'),
upd_prsn=child.get('upd_prsn'))
)
await db.execute(st)
await cls.update_leaf_node_flag(db)
else:
child['content_onum'] = content_onum
db_child = DataAstContentRela(**child)
db.add(db_child)
await db.flush()
await cls.update_leaf_node_flag(db)
@classmethod
async def delete_catalog_dao(cls, db: AsyncSession, catalog: DeleteDataCatalogModel):
"""
删除目录数据库操作
:param db: orm对象
:param catalog: 目录对象
:content_stat=0 作废
:return:
"""
content_onums = catalog.content_onums.split(',')
await db.execute(
update(DataAstContentRela)
.where(DataAstContentRela.content_onum.in_(content_onums))
.values(
rela_status=0,
rela_eff_end_date=datetime.now()
)
)
await db.execute(
update(DataAstContent)
.where(DataAstContent.content_onum.in_(content_onums))
.values(
content_stat=0,
upd_time=datetime.now()
)
)
await cls.update_leaf_node_flag(db)
@classmethod
async def moved_catalog_instr_dao(cls, db: AsyncSession, moved_catalog_data: dict):
"""
编辑目录数据库操作
:param db: orm对象
:param catalog: 需要更新的目录字典
:return:
"""
# content_onum = moved_catalog_data['content_onum']
stmt = (
update(DataAstContent)
.where(DataAstContent.content_onum == moved_catalog_data['content_onum'],
DataAstContent.supr_content_onum == moved_catalog_data['supr_content_onum'])
.values(
supr_content_onum=moved_catalog_data['supr_content_onum_after'],
upd_time=datetime.now()
))
await db.execute(stmt)
await cls.update_leaf_node_flag(db)
@classmethod
async def merge_catalog_instr_dao(cls, db: AsyncSession, merge_catalog_data: dict):
"""
编辑目录数据库操作
:param db: orm对象
:param catalog: 需要更新的目录字典
: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)
.values(
content_onum=merge_catalog_data['content_onum_after'],
rela_eff_begn_date=datetime.now()
)
)
await db.execute(stmt1)
stmt2 = (
update(DataAstContent)
.where(DataAstContent.content_onum == merge_catalog_data['content_onum'],
DataAstContent.supr_content_onum == merge_catalog_data['supr_content_onum'])
.values(content_stat='0')
)
await db.execute(stmt2)
await cls.update_leaf_node_flag(db)
@classmethod
async def removerel_data_ast_catalog_dao(cls, db: AsyncSession, removerel_catalog_data: dict):
"""
编辑资产关系数据库操作
:param db: orm对象
:param catalog: 需要更新的目录字典
:return:
"""
stmt = (
update(DataAstContentRela)
.where(DataAstContentRela.rela_onum == removerel_catalog_data['rela_onum'],
DataAstContentRela.content_onum == removerel_catalog_data['content_onum'])
.values(
rela_status=removerel_catalog_data['rela_status']
))
await db.execute(stmt)
await cls.update_leaf_node_flag(db)
@classmethod
async def moverel_data_ast_catalog_dao(cls, db: AsyncSession, moverel_catalog_data: dict):
"""
编辑资产关系数据库操作
:param db: orm对象
:param catalog: 需要更新的目录字典
:return:
"""
stmt = (
update(DataAstContentRela)
.where(DataAstContentRela.rela_onum == moverel_catalog_data['rela_onum'],
DataAstContentRela.content_onum == moverel_catalog_data['content_onum'])
.values(
content_onum=moverel_catalog_data['content_onum_after'],
rela_eff_end_date=datetime.now()
))
await db.execute(stmt)
await cls.update_leaf_node_flag(db)
@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: 数据资产目录分页列表
"""
# 修改子查询部分
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,
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,
)
.distinct()
.select_from(DataAstContent)
.outerjoin(subquery_t1, DataAstContent.content_onum == subquery_t1.c.content_onum) # 明确使用子查询别名
.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

7
vue-fastapi-backend/module_admin/entity/do/meta_do.py

@ -78,14 +78,15 @@ class MetadataClas(Base):
__tablename__ = 't_metadata_clas' __tablename__ = 't_metadata_clas'
clas_onum = Column(Integer, primary_key=True, comment='分类编号') clas_onum = Column(Integer, primary_key=True, comment='分类编号')
clas_pri_clas = Column(String(50, collation='utf8_general_ci'), comment='一级分类') # clas_pri_clas = Column(String(50, collation='utf8_general_ci'), comment='一级分类')
clas_scd_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_tmpl = Column(String(200, collation='utf8_general_ci'), comment='标签模板')
clas_thre_clas = Column(String(50, 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_name = Column(String(255, collation='utf8_general_ci'), comment='分类名称')
clas_eff_flag = Column(String(1, collation='utf8_general_ci'), default='0', comment='生效标志(0有效 1无效)') clas_eff_flag = Column(String(1, collation='utf8_general_ci'), default='0', comment='生效标志(0有效 1无效)')
rec_subm_prsn = Column(String(255, collation='utf8_general_ci'), comment='记录提交人') rec_subm_prsn = Column(String(255, collation='utf8_general_ci'), comment='记录提交人')
upd_time = Column(DateTime, comment='更新时间') upd_time = Column(DateTime, comment='更新时间')
belt_batch_content = Column(Integer, default=None, comment='分类')
class MetadataFldTabExtractInfo(Base): class MetadataFldTabExtractInfo(Base):

36
vue-fastapi-backend/module_admin/entity/do/metadata_config_do.py

@ -1,5 +1,5 @@
from datetime import datetime from datetime import datetime
from sqlalchemy import Column, String, Integer, DateTime, TIMESTAMP,Boolean, func,DECIMAL from sqlalchemy import Column,Text,Date, String, Integer, DateTime, TIMESTAMP,Boolean, func,DECIMAL
from config.database import Base from config.database import Base
@ -10,11 +10,12 @@ from config.database import Base
# __tablename__ = 't_metadata_clas' # __tablename__ = 't_metadata_clas'
# clas_onum = Column(Integer, primary_key=True, default=0, comment='标签序号') # clas_onum = Column(Integer, primary_key=True, default=0, comment='标签序号')
# clas_pri_clas = Column(String(50), default=None, comment='标签一级分类') # # clas_pri_clas = Column(String(50), default=None, comment='标签一级分类')
# clas_scd_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_thre_clas = Column(String(50), default=None, comment='标签三级分类')
# clas_name = Column(String(200), default=None, comment='标签名称') # clas_name = Column(String(200), default=None, comment='标签名称')
# clas_tmpl = Column(String(200), default=None, comment='标签模版') # clas_tmpl = Column(String(200), default=None, comment='标签模版')
# belt_batch_content = Column(Integer, default=None, comment='分类')
# clas_eff_flag = Column(String(1), default=None, comment='标签有效标志') # clas_eff_flag = Column(String(1), default=None, comment='标签有效标志')
# rec_subm_prsn = Column(String(64), 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='更新时间') # upd_time = Column(TIMESTAMP, default=func.now(), onupdate=func.now(), nullable=True, comment='更新时间')
@ -158,3 +159,30 @@ class DatasecConfig(Base):
ds_time = Column(DateTime, nullable=True, comment="调度时间") ds_time = Column(DateTime, nullable=True, comment="调度时间")
ds_ids = Column(String(50), nullable=True, comment="任务ID") ds_ids = Column(String(50), nullable=True, comment="任务ID")
schId = Column(String(50), nullable=True, comment="调度id") schId = Column(String(50), nullable=True, comment="调度id")
class DataAstContent(Base):
__tablename__ = "t_batch_content"
content_onum = Column(Integer, primary_key=True, autoincrement=True, comment='目录序号')
content_name = Column(String(255), nullable=False, comment='目录名称')
content_stat = Column(String(10), nullable=False, comment='目录状态(有效/废弃/停用)')
content_intr = Column(Text, comment='目录简介')
content_pic = Column(String(255), comment='目录负责人')
supr_content_onum = Column(Integer, comment='上级目录序号')
leaf_node_flag = Column(Integer, default=1, comment='叶子节点标志')
upd_prsn = Column(String(255), nullable=False, comment='更新人员')
upd_time = Column(DateTime, default=datetime.now, onupdate=datetime.now, comment='更新时间')
class DataAstContentRela(Base):
__tablename__ = "t_batch_content_rela"
rela_onum = Column(Integer, primary_key=True, autoincrement=True, comment='关系序号')
content_onum = Column(Integer, nullable=False, comment='目录序号')
ast_onum = Column(Integer, nullable=False, comment='资产序号')
rela_type = Column(String(50), default='归属关系', comment='关系类型')
rela_eff_begn_date = Column(Date, nullable=True, comment='关系生效开始日期')
rela_eff_end_date = Column(Date, nullable=True, comment='关系生效结束日期')
upd_prsn = Column(String(255), nullable=False, comment='更新人员')
rela_status = Column(String(18), nullable=True, comment='关系状态')

5
vue-fastapi-backend/module_admin/entity/vo/metadata_config_vo.py

@ -14,9 +14,8 @@ class MetadataClasModel(BaseModel):
model_config = ConfigDict(alias_generator=to_camel, from_attributes=True) model_config = ConfigDict(alias_generator=to_camel, from_attributes=True)
clas_onum: Optional[int] = Field(default=None, description='标签序号') clas_onum: Optional[int] = Field(default=None, description='标签序号')
clas_pri_clas: Optional[str] = Field(default=None, description='标签一级分类') belt_batch_content: Optional[int] = 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_name: Optional[str] = Field(default=None, description='标签名称')
clas_tmpl: 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='标签有效标志') clas_eff_flag: Optional[Literal['0', '1']] = Field(default=None, description='标签有效标志')

292
vue-fastapi-backend/module_admin/service/metadata_config_service.py

@ -9,6 +9,8 @@ from utils.common_util import CamelCaseUtil
from module_admin.entity.do.metadata_config_do import SecuBizConfigRela,TaskBizConfigRela # ORM 类 from module_admin.entity.do.metadata_config_do import SecuBizConfigRela,TaskBizConfigRela # ORM 类
from exceptions.exception import ServiceException,ServiceWarning from exceptions.exception import ServiceException,ServiceWarning
import uuid import uuid
from collections import defaultdict
from module_admin.entity.vo.data_ast_content_vo import DataCatalogPageQueryModel, DeleteDataCatalogModel,DataCatalogResponseWithChildren,DataCatalogMovedRequest,DataCatalogMergeRequest,DataCatalogChild,DataCatalogMoverelRequest
from module_admin.entity.vo.dataSource_vo import ProcessDefinition,ParmScheduleVo,ProcessInstancePage,ParmSchedule from module_admin.entity.vo.dataSource_vo import ProcessDefinition,ParmScheduleVo,ProcessInstancePage,ParmSchedule
from typing import List from typing import List
from datetime import datetime from datetime import datetime
@ -50,6 +52,9 @@ class MetadataConfigService:
existing = await MetadataConfigDao.get_clas_by_onum(query_db, page_object.clas_onum) existing = await MetadataConfigDao.get_clas_by_onum(query_db, page_object.clas_onum)
if existing: if existing:
raise ServiceException(message=f"主键重复,clas_onum={page_object.clas_onum} 已存在") raise ServiceException(message=f"主键重复,clas_onum={page_object.clas_onum} 已存在")
# 默认临时
if not page_object.belt_batch_content:
page_object.belt_batch_content=2
await MetadataConfigDao.add_metadata_clas_dao(query_db, page_object) await MetadataConfigDao.add_metadata_clas_dao(query_db, page_object)
await query_db.commit() await query_db.commit()
@ -69,7 +74,7 @@ class MetadataConfigService:
edit_data = page_object.model_dump(exclude_unset=True) edit_data = page_object.model_dump(exclude_unset=True)
# 当前记录旧主键(假设表单传入) # 当前记录旧主键(假设表单传入)
original_onum = page_object.original_clas_onum # 你需要在 model 中加上这个字段 original_onum = page_object.clas_onum # 你需要在 model 中加上这个字段
# 查询当前记录是否存在 # 查询当前记录是否存在
existing = await cls.get_metadata_clas_detail_services(query_db, original_onum) existing = await cls.get_metadata_clas_detail_services(query_db, original_onum)
@ -789,3 +794,288 @@ class MetadataConfigService:
async def get_task_biz_config_rela_list_services(cls, result_db: AsyncSession, biz_onum: int): async def get_task_biz_config_rela_list_services(cls, result_db: AsyncSession, biz_onum: int):
ai_session_list = await MetadataConfigDao.get_task_rela_by_biz_id(result_db, biz_onum) # 查询最新的20条 ai_session_list = await MetadataConfigDao.get_task_rela_by_biz_id(result_db, biz_onum) # 查询最新的20条
return CamelCaseUtil.transform_result(ai_session_list) return CamelCaseUtil.transform_result(ai_session_list)
# -------------------------------标签分类分级----------------------------
@classmethod
async def get_catalog_list_services(
cls, query_db: AsyncSession, query_object: DataCatalogPageQueryModel, user_id: int, is_page: bool = False
):
"""
获取数据目录列表信息service
:param query_db: orm对象
:param query_object: 查询参数对象
:param is_page: 是否开启分页
:return: 数据目录列表信息对象
"""
catalog_list_result = await MetadataConfigDao.get_catalog_list(query_db, query_object, user_id, is_page)
# 按contentOnum分组
grouped = defaultdict(list)
for item in catalog_list_result.rows:
grouped[item['contentOnum']].append(item)
nodes = {} # 存储所有处理后的节点
# 处理每个组,生成节点
for belt_data_std_content, items in grouped.items():
first_item = items[0]
is_leaf = first_item['leafNodeFlag'] == 1
rela_onum = first_item['relaOnum'] is not None
# 公共字段提取
common_fields = {
'contentOnum': first_item['contentOnum'],
'contentName': first_item['contentName'],
'contentStat': first_item['contentStat'],
'contentIntr': first_item['contentIntr'],
'contentPic': first_item['contentPic'],
'suprContentOnum': first_item['suprContentOnum'],
'leafNodeFlag': first_item['leafNodeFlag'],
'updPrsn': first_item['updPrsn'],
'updTime': first_item['updTime'],
'children': []
}
nodes[belt_data_std_content] = common_fields
# 构建父子关系
root = None
for belt_data_std_content, node in nodes.items():
supr = node['suprContentOnum']
if supr is None:
root = node
else:
parent = nodes.get(supr)
if parent:
parent['children'].append(node)
# 对每个父节点的children进行排序,将'临时的节点'放到最后
for belt_data_std_content, node in nodes.items():
if 'children' in node:
# 排序时,'临时的节点'会被放到最后
node['children'] = sorted(
node['children'],
key=lambda x: x['contentName'] == '临时',
reverse=False # True会将'临时的节点'排在最前面,False是排在最后
)
print('获取数据清单内容:',root)
catalog_list_result.rows = [root]
return catalog_list_result
@classmethod
async def delete_catalog_services(cls, query_db: AsyncSession, request: DeleteDataCatalogModel,user_id):
"""
删除数据目录信息service
:param query_db: orm对象
:param request: 删除数据目录请求对象
:return: 删除目录操作结果
"""
if request.content_onums:
content_onum_list = request.content_onums.split(',')
try:
for belt_data_std_content in content_onum_list:
catalog = await cls.get_catalog_detail_services(query_db, int(belt_data_std_content))
if not catalog:
raise ServiceException(message=f'目录ID {belt_data_std_content} 不存在')
await MetadataConfigDao.delete_catalog_dao(query_db, DeleteDataCatalogModel(content_onums=belt_data_std_content))
# await MetadataConfigDao.delete_ast_book_mark_rela_by_content_onum(query_db, int(belt_data_std_content), user_id)
await query_db.commit()
return CrudResponseModel(is_success=True, message='删除成功')
except Exception as e:
await query_db.rollback()
raise e
else:
raise ServiceException(message='传入目录id为空')
@classmethod
async def removerel_data_ast_catalog_services(cls, query_db: AsyncSession, request: DataCatalogChild):
"""
移除数据资产目录service
"""
removerel_catalog_data = {
'rela_onum': request.rela_onum,
'content_onum': request.content_onum,
'ast_onum': request.ast_onum,
'rela_type': request.rela_type,
'rela_eff_begn_date': request.rela_eff_begn_date,
'rela_eff_end_date': request.rela_eff_end_date,
'upd_prsn': request.upd_prsn,
'rela_status': request.rela_status
}
try:
await MetadataConfigDao.removerel_data_ast_catalog_dao(query_db, removerel_catalog_data)
await query_db.commit()
return CrudResponseModel(is_success=True, message='资产移除成功')
except Exception as e:
await query_db.rollback()
raise ServiceException(message=f"移除资产时发生错误: {str(e)}")
@classmethod
async def get_catalog_detail_services(cls, query_db: AsyncSession, belt_data_std_content: int):
"""
获取数据目录详细信息service
:param query_db: orm对象
:param belt_data_std_content: 数据目录ID
:return: 数据目录详细信息对象
"""
catalog_detail_result = await MetadataConfigDao.get_catalog_by_id(query_db, belt_data_std_content)
return catalog_detail_result
@classmethod
async def moved_catalog_instr_services(cls, query_db: AsyncSession, request: DataCatalogMovedRequest):
"""
移动数据目录service
"""
moved_catalog_data = {
'content_onum': request.content_onum,
'supr_content_onum': request.supr_content_onum,
'supr_content_onum_after': request.supr_content_onum_after
}
try:
await MetadataConfigDao.moved_catalog_instr_dao(query_db, moved_catalog_data)
await query_db.commit()
return CrudResponseModel(is_success=True, message='目录移动成功')
except Exception as e:
await query_db.rollback()
raise ServiceException(message=f"移动目录时发生错误: {str(e)}")
@classmethod
async def merge_catalog_instr_services(cls, query_db: AsyncSession, request: DataCatalogMergeRequest):
"""
移动数据目录service
"""
merge_catalog_data = {
'content_onum': request.content_onum,
'supr_content_onum': request.supr_content_onum,
'content_onum_after': request.content_onum_after,
'supr_content_onum_after': request.supr_content_onum_after
}
try:
await MetadataConfigDao.merge_catalog_instr_dao(query_db, merge_catalog_data)
await query_db.commit()
return CrudResponseModel(is_success=True, message='目录合并成功')
except Exception as e:
await query_db.rollback()
raise ServiceException(message=f"目录合并时发生错误: {str(e)}")
@classmethod
async def edit_catalog_child_services(cls, query_db: AsyncSession, request: DataCatalogResponseWithChildren):
"""
编辑数据目录信息service
:param query_db: orm对象
:param request: 编辑数据目录请求对象
:return: 编辑目录操作结果
"""
catalog_data = {
'content_onum': request.content_onum,
'content_name': request.content_name,
'content_stat': request.content_stat,
'content_intr': request.content_intr,
'content_pic': request.content_pic,
'supr_content_onum': request.supr_content_onum,
'leaf_node_flag': request.leaf_node_flag,
'upd_prsn': request.upd_prsn,
'children': [child.model_dump() for child in request.children] # 将 children 转换为字典列表
}
try:
for child in catalog_data["children"]:
# 设置 rela_eff_begn_date
if child.get("rela_eff_begn_date"):
child["rela_eff_begn_date"] = child["rela_eff_begn_date"].strftime("%Y-%m-%d %H:%M:%S")
else:
child["rela_eff_begn_date"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# 设置 rela_eff_end_date
if child.get("rela_eff_end_date"):
child["rela_eff_end_date"] = child["rela_eff_end_date"].strftime("%Y-%m-%d %H:%M:%S")
else:
child["rela_eff_end_date"] = datetime(year=2999, month=12, day=31, hour=0, minute=0, second=0).strftime("%Y-%m-%d %H:%M:%S")
child["upd_prsn"] = request.upd_prsn
child["rela_status"] = "1"
await MetadataConfigDao.edit_catalog_child_dao(query_db, catalog_data)
await query_db.commit()
return CrudResponseModel(is_success=True, message='更新成功')
except Exception as e:
await query_db.rollback()
raise ServiceException(message=f"更新目录时发生错误: {str(e)}")
@classmethod
async def add_catalog_services(cls, query_db: AsyncSession, request: DataCatalogResponseWithChildren):
"""
新增数据目录信息service
:param query_db: orm对象
:param request: 新增数据目录请求对象
:return: 新增目录操作结果
"""
catalog_data1 = {
'content_name': request.content_name,
'content_stat': request.content_stat,
'content_intr': request.content_intr,
'content_pic': request.content_pic,
'supr_content_onum': request.supr_content_onum,
'leaf_node_flag': request.leaf_node_flag,
'upd_prsn': request.upd_prsn
}
catalog_data2 = {
'content_name': request.content_name,
'content_stat': request.content_stat,
'content_intr': request.content_intr,
'content_pic': request.content_pic,
'supr_content_onum': request.supr_content_onum,
'leaf_node_flag': request.leaf_node_flag,
'upd_prsn': request.upd_prsn,
'children': [child.model_dump() for child in request.children] # 将 children 转换为字典列表
}
try:
for child in catalog_data2["children"]:
child["rela_eff_begn_date"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S"), # 设置默认值,当前时间
child["rela_eff_end_date"] = datetime(year=2999, month=12, day=31, hour=0, minute=0, second=0).strftime("%Y-%m-%d %H:%M:%S"), # 设置默认值,2999-12-31
child["upd_prsn"] = request.upd_prsn,
child["rela_status"] = "1"
new_catalog = await MetadataConfigDao.add_catalog_dao(query_db, catalog_data1, catalog_data2)
await query_db.commit()
return CrudResponseModel(is_success=True, message='新增成功', data=new_catalog)
except Exception as e:
await query_db.rollback()
raise ServiceException(message=f"创建目录时发生错误: {str(e)}")
@classmethod
async def edit_catalog_leaf_services(cls, query_db: AsyncSession,content_onum : int, leaf_node_flag : int):
"""
编辑数据目录信息service
:param query_db: orm对象
:param request: 编辑数据目录请求对象
:return: 编辑目录操作结果
"""
catalog_data1 = {
'content_onum': content_onum,
'leaf_node_flag': leaf_node_flag
}
try:
await MetadataConfigDao.edit_catalog_leaf_dao(query_db, catalog_data1)
await query_db.commit()
return CrudResponseModel(is_success=True, message='更新成功')
except Exception as e:
await query_db.rollback()
raise ServiceException(message=f"更新目录时发生错误: {str(e)}")

92
vue-fastapi-frontend/src/api/metadataConfig/directory.js

@ -0,0 +1,92 @@
import request from '@/utils/request'
export function getDirectoryTree(params) {
return request({
url: '/default-api/metadataConfig/cata/list',
method: 'get',
params,
})
}
export function delDirectory(id) {
return request({
url: `/default-api/metadataConfig/cata/${id}`,
method: 'delete',
})
}
export function addDirectoryCollection(data) {
return request({
url: '/default-api/metadataConfig/cata/bookmark ',
method: 'post',
data,
})
}
export function cancelDirectoryCollection(id) {
return request({
url: `/default-api/metadataConfig/cata/bookmark/${id}`,
method: 'delete',
})
}
export function delDirectoryAsset(data) {
return request({
url: '/default-api/metadataConfig/cata/removerel',
method: 'put',
data,
})
}
export function moveDirectory(data) {
return request({
url: '/default-api/metadataConfig/cata/moved',
method: 'put',
data,
})
}
export function mergeDirectory(data) {
return request({
url: '/default-api/metadataConfig/cata/merge',
method: 'put',
data,
})
}
export function moveDirectoryAsset(data) {
return request({
url: '/default-api/metadataConfig/cata/moverel',
method: 'put',
data,
})
}
export function addDirectory(data) {
return request({
url: '/default-api/metadataConfig/cata',
method: 'post',
data,
})
}
export function updateDirectory(data) {
return request({
url: `/default-api/metadataConfig/cata/edit`,
method: 'put',
data,
})
}
export function getDirectoryAsset(params) {
return request({
url: '/default-api/metadataConfig/cata/atree',
method: 'get',
params,
})
}
export function getDirectory(id) {
return request({
url: `/default-api/metadataConfig/cata/${id}`,
method: 'get',
})
}

171
vue-fastapi-frontend/src/views/metadataConfig/clas/components/AssetMoveDialog.vue

@ -0,0 +1,171 @@
<template>
<el-dialog width="800px" append-to-body :title="title" v-model="open">
<el-form label-width="100px" ref="formRef" :model="form" :rules="rules">
<el-row :gutter="16">
<el-col :span="11">
<el-form-item label="当前资产" prop="dataAstCnName">
<el-input :disabled="true" v-model="form.dataAstCnName" />
</el-form-item>
<el-form-item label="当前资产简介" prop="dataAstDesc">
<el-input
placeholder="自动带入"
type="textarea"
:disabled="true"
:rows="8"
v-model="form.dataAstDesc"
/>
</el-form-item>
</el-col>
<el-col :span="2">
<div class="arrow">
<span>········</span>
<el-icon><Right /></el-icon>
</div>
</el-col>
<el-col :span="11">
<el-form-item label="目标分类" prop="contentOnumAfter">
<el-tree-select
check-strictly
value-key="contentOnum"
placeholder="选择目标分类"
:default-expand-all="true"
:disabled="disabled"
:clearable="true"
:data="localDirectoryTree"
:props="{
value: 'contentOnum',
label: 'contentName',
children: 'children',
}"
v-model="form.contentOnumAfter"
@node-click="handleTargetCatalogNodeClick"
/>
</el-form-item>
<el-form-item label="目标分类简介" prop="contentIntrAfter">
<el-input
placeholder="自动带入"
type="textarea"
:disabled="true"
:rows="8"
v-model="form.contentIntrAfter"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="cancel">取消</el-button>
<el-button type="primary" :disabled="disabled" @click="submitForm"
>确定</el-button
>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { nextTick } from 'vue'
import { moveDirectoryAsset } from '@/api/metadataConfig/directory'
const props = defineProps({
directoryTree: {
type: Array,
required: true,
},
})
const filterTree = (tree, conditionFn) => {
return tree
.map((node) => {
//
const filteredChildren = node.children
? filterTree(node.children, conditionFn)
: []
//
if (conditionFn(node)) {
//
return {
...node,
children: filteredChildren,
}
}
// null
return null
})
.filter(Boolean) // null
}
const localDirectoryTree = computed(() => {
const tree = props.directoryTree
return filterTree(tree, (node) => node.contentOnum && !node.astOnum) //
})
const title = ref('')
const open = ref(false)
const disabled = ref(false)
const { proxy } = getCurrentInstance()
const form = ref({})
const rules = ref({
targetContentOnum: [
{ required: true, message: '目标分类不能为空', trigger: 'blur' },
],
})
const formRef = ref(null)
const openDialog = (row) => {
open.value = true
form.value = {
relaOnum: undefined,
contentOnum: undefined,
contentOnumAfter: undefined,
}
if (row.relaOnum) {
form.value = {
...form.value,
...row,
}
}
nextTick(() => {
formRef.value.clearValidate()
})
}
const handleTargetCatalogNodeClick = (data) => {
form.value = {
...form.value,
contentIntrAfter: data.contentIntr,
}
}
const emit = defineEmits(['onSuccess'])
const submitForm = () => {
formRef.value.validate((valid) => {
if (valid) {
moveDirectoryAsset(form.value).then((response) => {
proxy.$modal.msgSuccess('移动成功')
open.value = false
emit('onSuccess')
})
}
})
}
const cancel = () => {
open.value = false
}
defineExpose({ title, disabled, openDialog })
</script>
<style lang="scss" scoped>
.arrow {
display: flex;
font-size: 18px;
text-align: center;
margin: 8px auto;
span {
line-height: 18px;
}
}
</style>

193
vue-fastapi-frontend/src/views/metadataConfig/clas/components/FormDialog.vue

@ -0,0 +1,193 @@
<template>
<el-dialog width="600px" append-to-body :title="title" v-model="open">
<el-form label-width="100px" ref="formRef" :model="form" :rules="rules">
<el-form-item label="分类名称" prop="contentName">
<el-input
placeholder="请输入分类名称"
:disabled="disabled"
v-model="form.contentName"
/>
</el-form-item>
<el-form-item label="上级分类" prop="suprContentOnum">
<el-tree-select
check-strictly
value-key="contentOnum"
placeholder="请选择上级分类"
:default-expand-all="true"
:disabled="disabled"
:clearable="true"
:data="localDirectoryTree"
:props="{
value: 'contentOnum',
label: 'contentName',
children: 'children',
}"
v-model="form.suprContentOnum"
>
</el-tree-select>
</el-form-item>
<el-form-item label="负责人" prop="contentPic">
<el-input
placeholder="请输入负责人"
:disabled="disabled"
v-model="form.contentPic"
/>
</el-form-item>
<el-form-item label="分类简介" prop="contentIntr">
<el-input
placeholder="请输入分类简介"
type="textarea"
:disabled="disabled"
:rows="8"
v-model="form.contentIntr"
/>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="cancel">取消</el-button>
<el-button type="primary" :disabled="disabled" @click="submitForm"
>确定</el-button
>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { computed, nextTick } from 'vue'
import {
getDirectory,
addDirectory,
updateDirectory,
getDirectoryAsset,
} from '@/api/metadataConfig/directory'
const props = defineProps({
directoryTree: {
type: Array,
required: true,
},
})
const filterTree = (tree, conditionFn) => {
return tree
.map((node) => {
//
const filteredChildren = node.children
? filterTree(node.children, conditionFn)
: []
//
if (conditionFn(node)) {
//
return {
...node,
children: filteredChildren,
}
}
// null
return null
})
.filter(Boolean) // null
}
const localDirectoryTree = computed(() => {
const tree = props.directoryTree
return filterTree(tree, (node) => node.contentOnum && !node.astOnum) //
})
const title = ref('')
const open = ref(false)
const disabled = ref(false)
const { proxy } = getCurrentInstance()
const form = ref({})
const rules = ref({
contentName: [
{ required: true, message: '分类名称不能为空', trigger: 'blur' },
],
suprContentOnum: [
{ required: true, message: '上级分类不能为空', trigger: 'blur' },
],
})
const formRef = ref(null)
const openDialog = (row) => {
open.value = true
form.value = {
contentName: undefined,
suprContentOnum: undefined,
contentPic: undefined,
contentStat: '1', // 0-1-2-
contentIntr: undefined,
children: [],
}
if (row.contentOnum || row.suprContentOnum) {
form.value = {
...form.value,
...row,
assets:
row.children &&
row.children.length &&
row.children.find((i) => i.astOnum)
? [...row.children].map((i) => i.astOnum)
: [], //
}
}
nextTick(() => {
formRef.value.clearValidate()
})
}
const addTreeNodeId = (tree) => {
return tree.map((node, index) => {
return {
...node,
id: node.dataAssetCatalogAstno || index,
children:
node.children && node.children.length
? addTreeNodeId(node.children)
: [],
}
})
}
const emit = defineEmits(['onSuccess'])
const submitForm = () => {
formRef.value.validate((valid) => {
if (valid) {
const children = form.value.assets.reduce((arr, cur) => {
const item = form.value.children.find((i) => i.astOnum === cur)
if (!item) {
arr.push({
contentOnum: form.value.contentOnum,
astOnum: cur,
})
} else {
arr.push(item)
}
return arr
}, [])
form.value = {
...form.value,
children,
}
const request = form.value.contentOnum ? updateDirectory : addDirectory
request(form.value).then((response) => {
proxy.$modal.msgSuccess(
form.value.contentOnum ? '修改成功' : '新增成功'
)
open.value = false
emit('onSuccess')
})
}
})
}
const cancel = () => {
open.value = false
}
defineExpose({ title, disabled, openDialog })
</script>

175
vue-fastapi-frontend/src/views/metadataConfig/clas/components/MergerDialog.vue

@ -0,0 +1,175 @@
<template>
<el-dialog width="800px" append-to-body :title="title" v-model="open">
<el-form label-width="100px" ref="formRef" :model="form" :rules="rules">
<el-row :gutter="16">
<el-col :span="11">
<el-form-item label="当前目录" prop="contentName">
<el-input :disabled="true" v-model="form.contentName" />
</el-form-item>
<el-form-item label="当前目录简介" prop="contentIntr">
<el-input
placeholder="自动带入"
type="textarea"
:disabled="true"
:rows="8"
v-model="form.contentIntr"
/>
</el-form-item>
</el-col>
<el-col :span="2">
<div class="arrow">
<span>········</span>
<el-icon><Right /></el-icon>
</div>
</el-col>
<el-col :span="11">
<el-form-item label="目标目录" prop="contentOnumAfter">
<el-tree-select
check-strictly
value-key="contentOnum"
placeholder="选择目标目录"
:default-expand-all="true"
:disabled="disabled"
:clearable="true"
:data="localDirectoryTree"
:props="{
value: 'contentOnum',
label: 'contentName',
children: 'children',
}"
v-model="form.contentOnumAfter"
@node-click="handleTargetCatalogNodeClick"
/>
</el-form-item>
<el-form-item label="目标目录简介" prop="contentIntrAfter">
<el-input
placeholder="自动带入"
type="textarea"
:disabled="true"
:rows="8"
v-model="form.contentIntrAfter"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="cancel">取消</el-button>
<el-button type="primary" :disabled="disabled" @click="submitForm"
>确定</el-button
>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { nextTick } from 'vue'
import { mergeDirectory } from '@/api/metadataConfig/directory'
const props = defineProps({
directoryTree: {
type: Array,
required: true,
},
})
const filterTree = (tree, conditionFn) => {
return tree
.map((node) => {
//
const filteredChildren = node.children
? filterTree(node.children, conditionFn)
: []
//
if (conditionFn(node)) {
//
return {
...node,
children: filteredChildren,
}
}
// null
return null
})
.filter(Boolean) // null
}
const localDirectoryTree = computed(() => {
const tree = props.directoryTree
return filterTree(tree, (node) => node.contentOnum && !node.astOnum) //
})
const title = ref('')
const open = ref(false)
const disabled = ref(false)
const { proxy } = getCurrentInstance()
const form = ref({})
const rules = ref({
contentOnumAfter: [
{ required: true, message: '目标目录不能为空', trigger: 'blur' },
],
})
const formRef = ref(null)
const openDialog = (row) => {
open.value = true
form.value = {
contentOnum: undefined,
suprContentOnum: undefined,
contentIntr: undefined,
contentOnumAfter: undefined,
suprContentOnumAfter: undefined,
contentIntrAfter: undefined,
}
if (row.contentOnum) {
form.value = {
...form.value,
...row,
}
}
nextTick(() => {
formRef.value.clearValidate()
})
}
const handleTargetCatalogNodeClick = (data) => {
form.value = {
...form.value,
suprContentOnumAfter: data.suprContentOnum,
contentIntrAfter: data.contentIntr,
}
}
const emit = defineEmits(['onSuccess'])
const submitForm = () => {
formRef.value.validate((valid) => {
if (valid) {
mergeDirectory(form.value).then((response) => {
proxy.$modal.msgSuccess('合并成功')
open.value = false
emit('onSuccess')
})
}
})
}
const cancel = () => {
open.value = false
}
defineExpose({ title, disabled, openDialog })
</script>
<style lang="scss" scoped>
.arrow {
display: flex;
font-size: 18px;
text-align: center;
margin: 8px auto;
span {
line-height: 18px;
}
}
</style>

173
vue-fastapi-frontend/src/views/metadataConfig/clas/components/MoveDialog.vue

@ -0,0 +1,173 @@
<template>
<el-dialog width="800px" append-to-body :title="title" v-model="open">
<el-form label-width="100px" ref="formRef" :model="form" :rules="rules">
<el-row :gutter="16">
<el-col :span="11">
<el-form-item label="当前分类" prop="contentName">
<el-input :disabled="true" v-model="form.contentName" />
</el-form-item>
<el-form-item label="当前分类简介" prop="contentIntr">
<el-input
placeholder="自动带入"
type="textarea"
:disabled="true"
:rows="8"
v-model="form.contentIntr"
/>
</el-form-item>
</el-col>
<el-col :span="2">
<div class="arrow">
<span>········</span>
<el-icon><Right /></el-icon>
</div>
</el-col>
<el-col :span="11">
<el-form-item label="目标分类" prop="suprContentOnumAfter">
<el-tree-select
check-strictly
value-key="contentOnum"
placeholder="选择目标分类"
:default-expand-all="true"
:disabled="disabled"
:clearable="true"
:data="localDirectoryTree"
:props="{
value: 'contentOnum',
label: 'contentName',
children: 'children',
}"
v-model="form.suprContentOnumAfter"
@node-click="handleTargetCatalogNodeClick"
/>
</el-form-item>
<el-form-item label="目标分类简介" prop="contentIntrAfter">
<el-input
placeholder="自动带入"
type="textarea"
:disabled="true"
:rows="8"
v-model="form.contentIntrAfter"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="cancel">取消</el-button>
<el-button type="primary" :disabled="disabled" @click="submitForm"
>确定</el-button
>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { nextTick } from 'vue'
import { moveDirectory } from '@/api/metadataConfig/directory'
const props = defineProps({
directoryTree: {
type: Array,
required: true,
},
})
const filterTree = (tree, conditionFn) => {
return tree
.map((node) => {
//
const filteredChildren = node.children
? filterTree(node.children, conditionFn)
: []
//
if (conditionFn(node)) {
//
return {
...node,
children: filteredChildren,
}
}
// null
return null
})
.filter(Boolean) // null
}
const localDirectoryTree = computed(() => {
const tree = props.directoryTree
return filterTree(tree, (node) => node.contentOnum && !node.astOnum) //
})
const title = ref('')
const open = ref(false)
const disabled = ref(false)
const { proxy } = getCurrentInstance()
const form = ref({})
const rules = ref({
suprContentOnumAfter: [
{ required: true, message: '目标分类不能为空', trigger: 'blur' },
],
})
const formRef = ref(null)
const openDialog = (row) => {
open.value = true
form.value = {
contentOnum: undefined,
contentIntr: undefined,
suprContentOnum: undefined,
suprContentOnumAfter: undefined,
contentIntrAfter: undefined,
}
if (row.contentOnum) {
form.value = {
...form.value,
...row,
}
}
nextTick(() => {
formRef.value.clearValidate()
})
}
const handleTargetCatalogNodeClick = (data) => {
form.value = {
...form.value,
contentIntrAfter: data.contentIntr,
}
}
const emit = defineEmits(['onSuccess'])
const submitForm = () => {
formRef.value.validate((valid) => {
if (valid) {
moveDirectory(form.value).then((response) => {
proxy.$modal.msgSuccess('移动成功')
open.value = false
emit('onSuccess')
})
}
})
}
const cancel = () => {
open.value = false
}
defineExpose({ title, disabled, openDialog })
</script>
<style lang="scss" scoped>
.arrow {
display: flex;
font-size: 18px;
text-align: center;
margin: 8px auto;
span {
line-height: 18px;
}
}
</style>

452
vue-fastapi-frontend/src/views/metadataConfig/clas/index.vue

@ -1,10 +1,178 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-row :gutter="16">
<el-col :span="5">
<el-input
v-model="filterText"
style="width: 100%"
placeholder="搜索分类名称"
>
<template #prefix>
<el-icon><Search /></el-icon>
</template>
</el-input>
<div class="tree-box">
<el-tree
class="tree"
ref="treeRef"
node-key="tempId"
:default-expand-all="true"
:highlight-current="true"
:expand-on-click-node="false"
:data="directoryTree"
:props="defaultProps"
:filter-node-method="filterNode"
:current-node-key="currentNode.tempId"
@node-click="handleNodeClick"
>
<template #default="{ data }">
<div class="custom-tree-node">
<el-space :size="2">
<el-icon v-if="!isCollectionDirectory(data)">
<Folder />
</el-icon>
<el-icon v-else :style="isCollectionDirectory(data) ? { color: '#E6A23C' } : {}">
<FolderRemove />
</el-icon>
<span :style="isCollectionDirectory(data) ? { color: '#E6A23C' } : {}">
{{ data.contentName || data.dataAstCnName }}
</span> </el-space>
<div
v-if="!isCollectionDirectory(data)"
class="tree-node__action"
>
<template v-if="isAsset(data)">
<el-button
v-if="!isCollected(data)"
link
type="warning"
icon="Star"
@click="(e) => handleCollect(data, e)"
></el-button>
<el-button
v-else
link
type="warning"
style="margin-right: -2px"
@click="(e) => handleCollectionCancel(data, e)"
>
<el-icon slot="icon" size="18" color="#E6A23C">
<StarFilled />
</el-icon>
</el-button>
</template>
<el-dropdown
v-if="
!isCollection(data) &&
(isDirectory(data) || isRoot(data)) &&
hasPermiOr([
'dataAsset:directory:add',
'dataAsset:directory:edit',
'dataAsset:directory:remove',
'dataAsset:directory:move',
'dataAsset:directory:merge',
])
"
placement="right-start"
@command="(command) => handleCommand(command, data)"
>
<el-button
style="margin-left: 4px"
link
type="primary"
icon="Menu"
></el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item
v-if="
isRoot(data) &&
hasPermiOr(['dataAsset:directory:add'])
"
command="handleAddDialogOpen"
>
新增分类
</el-dropdown-item>
<template v-if="isDirectory(data)">
<el-dropdown-item
v-if="hasPermiOr(['dataAsset:directory:add'])"
command="handleAddDialogOpen"
>
新增分类
</el-dropdown-item>
<el-dropdown-item
v-if="hasPermiOr(['dataAsset:directory:edit'])"
command="handleEditDialogOpen"
>
修改分类
</el-dropdown-item>
<el-dropdown-item
v-if="hasPermiOr(['dataAsset:directory:remove'])"
command="handleDelete"
>
删除分类
</el-dropdown-item>
<el-dropdown-item
v-if="hasPermiOr(['dataAsset:directory:move'])"
command="handleMoveDialogOpen"
>
移动分类
</el-dropdown-item>
<el-dropdown-item
v-if="hasPermiOr(['dataAsset:directory:merge'])"
command="handleMergerDialogOpen"
>
合并分类
</el-dropdown-item>
</template>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-dropdown
v-if="
!isCollection(data) &&
isAsset(data) &&
hasPermiOr([
'dataAsset:asset:remove',
'dataAsset:asst:move',
])
"
placement="right-start"
@command="(command) => handleCommand(command, data)"
>
<el-button
style="margin-left: 4px"
link
type="primary"
icon="Menu"
></el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item
v-if="hasPermiOr(['dataAsset:asset:remove'])"
command="handleAssetDelete"
>
删除资产
</el-dropdown-item>
<el-dropdown-item
v-if="hasPermiOr(['dataAsset:asst:move'])"
command="handleAssetMoveDialogOpen"
>
移动资产
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</div>
</template>
</el-tree>
</div>
</el-col>
<el-col :span="19">
<el-row :gutter="10" class="mb8"> <el-row :gutter="10" class="mb8">
<el-form :inline="true" :model="queryForm" > <el-form :inline="true" :model="queryForm" >
<el-form-item label="标签一级分类">
<el-input v-model="queryForm.clasPriClas" placeholder="请输入标签一级分类" clearable />
</el-form-item>
<el-form-item label="标签名称"> <el-form-item label="标签名称">
<el-input v-model="queryForm.clasName" placeholder="请输入标签名称" clearable /> <el-input v-model="queryForm.clasName" placeholder="请输入标签名称" clearable />
</el-form-item> </el-form-item>
@ -55,9 +223,7 @@
> >
<el-table-column type="selection" width="55" /> <el-table-column type="selection" width="55" />
<el-table-column prop="clasOnum" label="标签序号" width="200" /> <el-table-column prop="clasOnum" label="标签序号" width="200" />
<el-table-column prop="clasPriClas" label="标签一级分类" width="150" />
<el-table-column prop="clasScdClas" label="标签二级分类" width="150" />
<el-table-column prop="clasThreClas" label="标签三级分类" width="150" />
<el-table-column prop="clasName" label="标签名称" width="200" /> <el-table-column prop="clasName" label="标签名称" width="200" />
<el-table-column prop="clasTmpl" label="标签模版" width="200" /> <el-table-column prop="clasTmpl" label="标签模版" width="200" />
<el-table-column prop="clasEffFlag" label="有效标志" width="100"> <el-table-column prop="clasEffFlag" label="有效标志" width="100">
@ -80,6 +246,10 @@
v-model:limit="queryForm.pageSize" v-model:limit="queryForm.pageSize"
@pagination="getList" @pagination="getList"
/> />
</el-col>
</el-row>
<el-dialog <el-dialog
:title="title" :title="title"
v-model="open" v-model="open"
@ -97,21 +267,33 @@
<el-form-item label="标签序号" prop="clasPriClas"> <el-form-item label="标签序号" prop="clasPriClas">
<el-input v-model="form.clasOnum" autocomplete="off" type="number" :disabled="title != '新增标签信息'"/> <el-input v-model="form.clasOnum" autocomplete="off" type="number" :disabled="title != '新增标签信息'"/>
</el-form-item> </el-form-item>
<el-form-item label="标签一级分类" prop="clasPriClas">
<el-input v-model="form.clasPriClas" autocomplete="off" />
</el-form-item>
<el-form-item label="标签二级分类" prop="clasScdClas">
<el-input v-model="form.clasScdClas" autocomplete="off" />
</el-form-item>
<el-form-item label="标签三级分类" prop="clasThreClas">
<el-input v-model="form.clasThreClas" autocomplete="off" />
</el-form-item>
<el-form-item label="标签名称" prop="clasName"> <el-form-item label="标签名称" prop="clasName">
<el-input v-model="form.clasName" autocomplete="off" /> <el-input v-model="form.clasName" autocomplete="off" />
</el-form-item> </el-form-item>
<el-form-item label="标签模版" prop="clasTmpl"> <el-form-item label="标签模版" prop="clasTmpl">
<el-input v-model="form.clasTmpl" autocomplete="off" /> <el-input v-model="form.clasTmpl" autocomplete="off" />
</el-form-item> </el-form-item>
<el-form-item label="标签分类">
<el-tree-select
check-strictly
value-key="contentOnum"
placeholder="请选择标签分类"
:default-expand-all="true"
:clearable="true"
:data="directoryTree"
:check-strictly="false"
:props="{
value: 'contentOnum',
label: 'contentName',
children: 'children',
// disabled: (data) => data.children && data.children.length > 0, //
}"
v-model="form.beltBatchContent"
>
</el-tree-select>
</el-form-item>
<el-form-item label="有效标志" prop="clasEffFlag"> <el-form-item label="有效标志" prop="clasEffFlag">
<el-select v-model="form.clasEffFlag" placeholder="请选择有效标志"> <el-select v-model="form.clasEffFlag" placeholder="请选择有效标志">
<el-option label="有效" value="1" /> <el-option label="有效" value="1" />
@ -124,22 +306,59 @@
<el-button type="primary" @click="submitForm">保存</el-button> <el-button type="primary" @click="submitForm">保存</el-button>
</template> </template>
</el-dialog> </el-dialog>
<FormDialog
ref="formDialogRef"
:directoryTree="directoryTree"
@onSuccess="setDirectoryTree"
/>
<MoveDialog
ref="moveDialogRef"
:directoryTree="directoryTree"
@onSuccess="setDirectoryTree"
/>
<MergerDialog
ref="mergerDialogRef"
:directoryTree="directoryTree"
@onSuccess="setDirectoryTree"
/>
<AssetMoveDialog
ref="assetMoveDialogRef"
:directoryTree="directoryTree"
@onSuccess="setDirectoryTree"
/>
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref, reactive, onMounted } from 'vue' import { ref, reactive, onMounted } from 'vue'
import { ElMessageBox, ElMessage } from 'element-plus' import { ElMessageBox, ElMessage } from 'element-plus'
import auth from '@/plugins/auth'
import { import {
listMetadataClas, listMetadataClas,
addMetadataClas, addMetadataClas,
updateMetadataClas, updateMetadataClas,
delMetadataClas delMetadataClas
} from '@/api/metadataConfig/metadataConfig' } from '@/api/metadataConfig/metadataConfig'
import {
getDirectoryTree,
delDirectory,
delDirectoryAsset,
addDirectoryCollection,
cancelDirectoryCollection,
} from '@/api/metadataConfig/directory'
const { hasPermiOr } = auth
const { proxy } = getCurrentInstance()
import FormDialog from './components/FormDialog.vue'
import MoveDialog from './components/MoveDialog.vue'
import MergerDialog from './components/MergerDialog.vue'
import AssetMoveDialog from './components/AssetMoveDialog.vue'
const queryForm = reactive({ const queryForm = reactive({
clasPriClas: '', clasPriClas: '',
clasName: '', clasName: '',
beltBatchContent:null,
pageNum: 1, pageNum: 1,
pageSize: 10 pageSize: 10
}) })
@ -149,32 +368,185 @@ const total = ref(0) // 总条数
const loading = ref(false) const loading = ref(false)
const open = ref(false) const open = ref(false)
const title = ref('') const title = ref('')
const handleMoveDialogOpen = (data) => {
moveDialogRef.value.title = '移动分类'
moveDialogRef.value.openDialog(data)
}
const mergerDialogRef = ref(null)
const handleMergerDialogOpen = (data) => {
mergerDialogRef.value.title = '合并分类'
mergerDialogRef.value.openDialog(data)
}
const handleCollect = (data, e) => {
e.stopPropagation()
addDirectoryCollection({
dataAstNo: String(data.dataAstNo),
userId: String(userStore.onum),
}).then(() => {
proxy.$modal.msgSuccess('收藏成功')
setDirectoryTree()
})
}
const handleCollectionCancel = (data, e) => {
e.stopPropagation()
cancelDirectoryCollection(data.relaOnum).then(() => {
proxy.$modal.msgSuccess('取消成功')
setDirectoryTree()
})
}
const clasFormRef = ref(null) const clasFormRef = ref(null)
const form = reactive({ const form = reactive({
clasOnum: null, clasOnum: null,
clasPriClas: '', beltBatchContent: null,
clasScdClas: '',
clasThreClas: '',
clasName: '', clasName: '',
clasTmpl: '', clasTmpl: '',
clasEffFlag: '', clasEffFlag: '',
recSubmPrsn: '' recSubmPrsn: ''
}) })
const currentNode = ref({})
const handleCommand = (command, data) => {
const strategy = {
handleAddDialogOpen: handleAddDialogOpen,
handleEditDialogOpen: handleEditDialogOpen,
handleDelete: handleDelete,
handleMoveDialogOpen: handleMoveDialogOpen,
handleMergerDialogOpen: handleMergerDialogOpen,
handleAssetDelete: handleAssetDelete,
handleAssetMoveDialogOpen: handleAssetMoveDialogOpen,
}
strategy[command](data)
}
const formDialogRef = ref(null)
const handleAddDialogOpen = (data) => {
formDialogRef.value.title = '新增分类'
formDialogRef.value.openDialog({
suprContentOnum: data.contentOnum,
})
}
const handleAssetDelete = (data) => {
ElMessageBox.confirm(`确定删除 ${data.dataAstCnName} 资产吗?`, '资产删除', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
delDirectoryAsset({
...data,
relaStatus: '0', // 0-1-
}).then(() => {
proxy.$modal.msgSuccess('删除成功')
setDirectoryTree()
})
})
}
const assetMoveDialogRef = ref(null)
const handleAssetMoveDialogOpen = (data) => {
assetMoveDialogRef.value.title = '移动资产'
assetMoveDialogRef.value.openDialog(data)
}
const handleEditDialogOpen = (data) => {
formDialogRef.value.title = '修改分类'
formDialogRef.value.openDialog(data)
}
const moveDialogRef = ref(null)
const handleDelete = (data) => {
ElMessageBox.confirm(
`确定删除 ${data.contentName} 分类吗?`,
'分类删除',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
).then(() => {
delDirectory(data.contentOnum).then(() => {
proxy.$modal.msgSuccess('删除成功')
setDirectoryTree()
})
})
}
const rules = { const rules = {
clasPriClas: [{ required: true, message: '请输入标签一级分类', trigger: 'blur' }],
clasOnum: [{ required: true, message: '请输入标签序号', trigger: 'blur' }], clasOnum: [{ required: true, message: '请输入标签序号', trigger: 'blur' }],
clasName: [{ required: true, message: '请输入标签名称', trigger: 'blur' }], clasName: [{ required: true, message: '请输入标签名称', trigger: 'blur' }],
clasEffFlag: [{ required: true, message: '请选择有效标志', trigger: 'change' }] clasEffFlag: [{ required: true, message: '请选择有效标志', trigger: 'change' }]
} }
const selectedRows = ref([]) const selectedRows = ref([])
const directoryTableData = ref([])
function handleSelectionChange(val) { function handleSelectionChange(val) {
selectedRows.value = val selectedRows.value = val
} }
//
const directoryTree = ref([])
const setDirectoryTree = () => {
return getDirectoryTree({
pageSize: 999,
}).then(({ rows }) => {
directoryTree.value = addTreeNodeId(rows)
})
}
/** 增加临时ID作为树节点的唯一键值 */
const addTreeNodeId = (tree) => {
return tree.map((node) => {
return {
...node,
tempId: node.astOnum || node.contentOnum,
children:
node.children && node.children.length
? addTreeNodeId(node.children)
: [],
}
})
}
setDirectoryTree().then(async () => {
if (directoryTree.value.length) {
currentNode.value = directoryTree.value[0]
directoryTableData.value = directoryTree.value[0].children || []
}
})
const handleNodeClick = async (data) => {
if(data.contentOnum==1){
queryForm.beltBatchContent=null
form.beltBatchContent=null
}else{
form.beltBatchContent=data.contentOnum
queryForm.beltBatchContent=data.contentOnum
}
handleSearch();
}
const filterText = ref(undefined)
const treeRef = ref(null)
watch(filterText, (val) => {
treeRef.value.filter(val)
})
const filterNode = (value, data) => {
if (!value) return true
if (data.contentName) return data.contentName.includes(value)
if (data.dataAstCnName) return data.dataAstCnName.includes(value)
}
//
const isRoot = (data) => data.contentOnum === 1
//
const isCollectionDirectory = (data) => data.contentName === '临时'
const isCollection = (data) => {
return false
}
//
const isDirectory = (data) => data.contentOnum && !isRoot(data) && !data.astOnum
//
const isAsset = (data) => data.astOnum
async function getList() { async function getList() {
loading.value = true loading.value = true
@ -211,9 +583,7 @@ function openAddDialog() {
title.value = '新增标签信息' title.value = '新增标签信息'
Object.assign(form, { Object.assign(form, {
clasOnum: null, clasOnum: null,
clasPriClas: '',
clasScdClas: '',
clasThreClas: '',
clasName: '', clasName: '',
clasTmpl: '', clasTmpl: '',
clasEffFlag: '', clasEffFlag: '',
@ -298,3 +668,41 @@ onMounted(() => {
}) })
</script> </script>
<style lang="scss" scoped>
.tree-box {
overflow: auto;
}
.tree {
margin-top: 10px;
min-width: 260px;
}
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
.tree-node__action {
padding: 0 8px;
display: flex;
justify-content: flex-end;
}
}
:deep(
.el-descriptions__body
.el-descriptions__table.is-bordered
.el-descriptions__cell
) {
width: 80px !important;
}
.faq {
white-space: pre-wrap;
}
iframe {
border: none;
}
</style>

Loading…
Cancel
Save