Browse Source

标准代码提交

master
si@aidatagov.com 1 month ago
parent
commit
3aa00c85c9
  1. 236
      vue-fastapi-backend/module_admin/controller/datastd_controller.py
  2. 431
      vue-fastapi-backend/module_admin/dao/datastd_dao.py
  3. 60
      vue-fastapi-backend/module_admin/entity/do/datastd_do.py
  4. 34
      vue-fastapi-backend/module_admin/entity/vo/datastd_vo.py
  5. 420
      vue-fastapi-backend/module_admin/service/datastd_service.py
  6. 110
      vue-fastapi-frontend/src/api/datastd/directory.js
  7. 50
      vue-fastapi-frontend/src/api/datastd/std.js
  8. 203
      vue-fastapi-frontend/src/views/datastd/main/components/AddEditForm.vue
  9. 171
      vue-fastapi-frontend/src/views/datastd/main/components/AssetMoveDialog.vue
  10. 193
      vue-fastapi-frontend/src/views/datastd/main/components/FormDialog.vue
  11. 175
      vue-fastapi-frontend/src/views/datastd/main/components/MergerDialog.vue
  12. 173
      vue-fastapi-frontend/src/views/datastd/main/components/MoveDialog.vue
  13. 651
      vue-fastapi-frontend/src/views/datastd/main/index.vue
  14. 269
      vue-fastapi-frontend/src/views/datastd/stddict/index.vue

236
vue-fastapi-backend/module_admin/controller/datastd_controller.py

@ -6,13 +6,15 @@ from config.get_db import get_db
from module_admin.entity.vo.user_vo import CurrentUserModel
from module_admin.annotation.log_annotation import Log
from module_admin.aspect.interface_auth import CheckUserInterfaceAuth
from module_admin.entity.vo.datastd_vo import DataStdCodeModel, DataStdCodePageQueryModel, DeleteDataStdModel,DataStdDictModel,DataStdDictPageQueryModel
from module_admin.entity.vo.datastd_vo import DataStdCodeModel, DataStdCodePageQueryModel, DeleteDataStdModel,DataStdDictModel,DataStdDictPageQueryModel,DataStdMainModel,DataStdMainPageQueryModel
from module_admin.service.datastd_service import DataStdService
from module_admin.service.login_service import LoginService
from utils.log_util import logger
from utils.page_util import PageResponseModel
from utils.response_util import ResponseUtil
import uuid
from module_admin.entity.vo.data_ast_content_vo import DataCatalogPageQueryModel, DeleteDataCatalogModel,DataCatalogResponseWithChildren,DataAssetCatalogTreeResponse,DataCatalogMovedRequest,DataCatalogMergeRequest,DataCatalogChild,DataCatalogMoverelRequest
from pydantic_validation_decorator import ValidateFields
datastdController = APIRouter(prefix='/datastd', dependencies=[Depends(LoginService.get_current_user)])
@ -210,6 +212,238 @@ async def delete_std_dict(
# ----------------------------------------------------------------标准目录----------------------------------------------------------------------------------------------------
@datastdController.get(
'/cata/list', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('system:data_catalog:list'))]
)
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 DataStdService.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)
@datastdController.get(
'/cata/atree',response_model=DataAssetCatalogTreeResponse,dependencies=[Depends(CheckUserInterfaceAuth('system:data_catalog:atree'))],summary="Data Asset Tree Query"
)
async def get_data_asset_catalog_tree(query_db: AsyncSession = Depends(get_db)):
try:
logger.debug("开始获取数据资产目录树")
catalog_tree_result = await DataStdService.get_data_asset_catalog_tree_services(query_db)
logger.info('数据资产树获取成功')
return ResponseUtil.success(data=catalog_tree_result)
except Exception as e:
logger.error(f"数据资产树获取失败: {str(e)}", exc_info=True)
return ResponseUtil.error(msg="数据查询异常,请联系管理员")
@datastdController.post('/cata', dependencies=[Depends(CheckUserInterfaceAuth('system:data_catalog:add'))])
@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 DataStdService.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 DataStdService.edit_catalog_leaf_services(query_db,supr_content_onum, 0)
else:
logger.error(add_result.message)
# 返回标准化响应
return ResponseUtil.success(
msg=add_result.message
)
@datastdController.put('/cata/edit', dependencies=[Depends(CheckUserInterfaceAuth('system:data_catalog: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 DataStdService.edit_catalog_child_services(query_db, edit_catalog)
logger.info(edit_result.message)
# 返回标准化响应
return ResponseUtil.success(
msg=edit_result.message
)
@datastdController.put('/cata/moved', dependencies=[Depends(CheckUserInterfaceAuth('system:data_catalog:edit'))])
@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 DataStdService.moved_catalog_instr_services(query_db, moved_catalog)
logger.info(moved_result.message)
# 返回标准化响应
return ResponseUtil.success(
msg=moved_result.message
)
@datastdController.put('/cata/merge', dependencies=[Depends(CheckUserInterfaceAuth('system:data_catalog:edit'))])
@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 DataStdService.merge_catalog_instr_services(query_db, merge_catalog)
logger.info(merge_result.message)
# 返回标准化响应
return ResponseUtil.success(
msg=merge_result.message
)
@datastdController.put('/cata/removerel', dependencies=[Depends(CheckUserInterfaceAuth('system:data_catalog:edit'))])
@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 DataStdService.removerel_data_ast_catalog_services(query_db, removerel_catalog)
logger.info(removerel_result.message)
# 返回标准化响应
return ResponseUtil.success()
@datastdController.put('/cata/moverel', dependencies=[Depends(CheckUserInterfaceAuth('system:data_catalog:edit'))])
@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 DataStdService.moverel_data_ast_catalog_services(query_db, moverel_catalog)
logger.info(moverel_result.message)
# 返回标准化响应
return ResponseUtil.success()
@datastdController.delete('/cata/{content_onums}', dependencies=[Depends(CheckUserInterfaceAuth('system:data_catalog:remove'))])
@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 DataStdService.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)
#----------------------------------------------数据标准--------------------------------------------------------------------------------------------------------------------------
@datastdController.get(
'/stdmain/main/list', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('datastd:stdmain:main:list'))]
)
async def get_std_main_list(
request: Request,
main_page_query: DataStdMainPageQueryModel = Depends(DataStdMainPageQueryModel.as_query),
query_db: AsyncSession = Depends(get_db),
):
main_page_query_result = await DataStdService.get_std_main_list(query_db, main_page_query, is_page=True)
logger.info('获取数据标准列表成功')
return ResponseUtil.success(model_content=main_page_query_result)
@datastdController.get(
'/stdmain/main/{id}', response_model=DataStdMainModel, dependencies=[Depends(CheckUserInterfaceAuth('datastd:stdmain:main:list'))]
)
async def query_detail_main(request: Request, id: str, query_db: AsyncSession = Depends(get_db)):
config_detail_result = await DataStdService.get_std_main_by_id(query_db, id)
logger.info(f'获取数据标准ID为{id}的信息成功')
return ResponseUtil.success(data=config_detail_result)
@datastdController.post('/stdmain/main', dependencies=[Depends(CheckUserInterfaceAuth('datastd:stdmain:main:add'))])
@Log(title='数据标准', business_type=BusinessType.INSERT)
async def add_std_main(
request: Request,
add_std_main: DataStdMainModel,
query_db: AsyncSession = Depends(get_db),
current_user: CurrentUserModel = Depends(LoginService.get_current_user),
):
add_std_main.create_by = current_user.user.user_name
add_std_main.create_time = datetime.now()
add_std_main.update_by = current_user.user.user_name
add_std_main.update_time = datetime.now()
add_std_main_result = await DataStdService.add_std_main(query_db, add_std_main)
logger.info(add_std_main_result.message)
return ResponseUtil.success(msg=add_std_main_result.message)
@datastdController.put('/stdmain/main', dependencies=[Depends(CheckUserInterfaceAuth('datastd:stdmain:main:edit'))])
@Log(title='数据标准', business_type=BusinessType.UPDATE)
async def edit_std_main(
request: Request,
edit_std_main: DataStdMainModel,
query_db: AsyncSession = Depends(get_db),
current_user: CurrentUserModel = Depends(LoginService.get_current_user),
):
edit_std_main.update_by = current_user.user.user_name
edit_std_main.update_time = datetime.now()
edit_std_main_result = await DataStdService.edit_std_main(query_db, edit_std_main)
logger.info(edit_std_main_result.message)
return ResponseUtil.success(msg=edit_std_main_result.message)
@datastdController.delete('/stdmain/main/{id}', dependencies=[Depends(CheckUserInterfaceAuth('datastd:stdmain:main:remove'))])
@Log(title='数据标准', business_type=BusinessType.DELETE)
async def delete_std_main(
request: Request,
id: str,
query_db: AsyncSession = Depends(get_db),
):
delete_std_main_result = await DataStdService.delete_std_main(query_db, id)
logger.info(delete_std_main_result.message)
return ResponseUtil.success(msg=delete_std_main_result.message)

431
vue-fastapi-backend/module_admin/dao/datastd_dao.py

@ -1,10 +1,12 @@
from sqlalchemy import delete, select, update, desc,or_
from sqlalchemy import delete, select, update, desc,or_,not_
from sqlalchemy.ext.asyncio import AsyncSession
from module_admin.entity.do.datastd_do import DataStdCode,DataStdDict
from module_admin.entity.vo.datastd_vo import DataStdCodeModel,DataStdDictModel
from module_admin.entity.do.datastd_do import DataStdCode,DataStdDict,DataAstContent,DataAstContentRela,DataStdMain
from module_admin.entity.vo.datastd_vo import DataStdCodeModel,DataStdDictModel,DataStdMainModel
from module_admin.entity.do.dept_do import SysDept
from utils.page_util import PageUtil
from sqlalchemy.orm import aliased
from module_admin.entity.vo.data_ast_content_vo import DataCatalogPageQueryModel, DeleteDataCatalogModel,DataCatalogChild
from datetime import datetime
class DataStdDao:
@ -283,3 +285,426 @@ class DataStdDao:
)
).scalars().first()
return List
# 数据标准目录
@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
#------------------------------------------------------------数据标准(658行)-------------------------------------------------------------------------------------------------
@classmethod
async def get_std_main_list(cls, db: AsyncSession, query_object: DataStdMainModel, is_page: bool = False):
filters = []
if query_object.std_name:
filters.append(DataStdMain.std_name.like(f"%{query_object.std_name}%"))
if query_object.std_code:
filters.append(DataStdMain.std_code.like(f"%{query_object.std_code}%"))
if query_object.sys_id:
filters.append(DataStdMain.sys_id == query_object.sys_id)
if query_object.std_type:
filters.append(DataStdMain.std_type == query_object.std_type)
if query_object.std_status:
filters.append(DataStdMain.std_status == query_object.std_status)
query = select(DataStdMain).where(*filters).order_by(desc(DataStdMain.create_time))
return await PageUtil.paginate(db, query, query_object.page_num, query_object.page_size, is_page)
@classmethod
async def add_std_main(cls, db: AsyncSession, model: DataStdMainModel):
col = DataStdMain(**model.model_dump())
db.add(col)
await db.flush()
return col
@classmethod
async def delete_std_main(cls, db: AsyncSession, Id: str):
await db.execute(delete(DataStdMain).where(DataStdMain.id == Id))
@classmethod
async def update_std_main(cls, db: AsyncSession, update_data: DataStdMainModel):
await db.execute(update(DataStdMain).where(DataStdMain.id == update_data.id).values(**update_data.model_dump()))
await db.flush()
@classmethod
async def get_std_main_by_id(cls, db: AsyncSession, Id: str):
col = await db.execute(select(DataStdMain).where(DataStdMain.id == Id))
return col.scalars().first()
@classmethod
async def get_data_main_by_info(cls, db: AsyncSession, query_object: DataStdMainModel):
col = await db.execute(
select(DataStdMain).where(
DataStdMain.std_name == query_object.std_name if query_object.std_name else True,
DataStdMain.std_code == query_object.std_code if query_object.std_code else True,
DataStdMain.std_num == query_object.std_num if query_object.std_num else True,
DataStdMain.sys_id == query_object.sys_id if query_object.sys_id else True,
DataStdMain.std_type == query_object.std_type if query_object.std_type else True,
DataStdMain.std_status == query_object.std_status if query_object.std_status else True
)
)
return col.scalars().first()

60
vue-fastapi-backend/module_admin/entity/do/datastd_do.py

@ -1,5 +1,6 @@
from sqlalchemy import Column, Integer, String, DateTime, Boolean,BigInteger
from sqlalchemy import Column, Integer, String, DateTime,Text, DateTime,Date, BigInteger
from config.database import Base
from datetime import datetime
# 数据标准模块相关表
@ -54,3 +55,60 @@ class DataStdDict(Base):
tech_dept_id = Column(BigInteger, default=None, comment='技术认责部门')
buss_user = Column(String(20), default=None, comment='业务认责人员')
tech_user = Column(String(20), default=None, comment='技术认责人员')
class DataAstContent(Base):
__tablename__ = "t_data_std_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_data_std_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='关系状态')
class DataStdMain(Base):
"""
数据标准表
"""
__tablename__ = 't_datastd_main'
id = Column(String(50), primary_key=True, comment='标准代码Id')
create_by = Column(String(20), default='', comment='创建者')
create_time = Column(DateTime, nullable=True, default=None, comment='创建时间')
update_by = Column(String(20), default='', comment='更新者')
update_time = Column(DateTime, nullable=True, default=None, comment='更新时间')
std_num = Column(String(50), default=None, comment='标准编号')
std_code = Column(String(50), default=None, comment='标准英文名')
std_name = Column(String(200), default=None, comment='标准中文名')
std_type = Column(String(1), default=None, comment='标准类型(0:基础数据 1:指标数据)')
sys_name = Column(String(50), default=None, comment='归属系统')
sys_id = Column(Integer, default=None, comment='归属系统Id')
std_menu = Column(String(200), default=None, comment='标准业务定义')
code_num = Column(String(50), default=None, comment='代码编号')
std_status = Column(String(1), default=None, comment='标准状态(1:有效 0:无效)')
buss_dept_id = Column(BigInteger, default=None, comment='业务认责部门')
tech_dept_id = Column(BigInteger, default=None, comment='技术认责部门')
buss_user = Column(String(20), default=None, comment='业务认责人员')
tech_user = Column(String(20), default=None, comment='技术认责人员')
content_onum = Column(Integer, default=None, comment='分类')
std_src = Column(String(20), default=None, comment='标准来源')
data_clas = Column(String(20), default=None, comment='数据类别')

34
vue-fastapi-backend/module_admin/entity/vo/datastd_vo.py

@ -87,3 +87,37 @@ class DataStdDictPageQueryModel(DataStdDictModel):
"""
page_num: int = Field(default=1, description='当前页码')
page_size: int = Field(default=10, description='每页记录数')
class DataStdMainModel(BaseModel):
"""
标准代码表对应Pydantic模型 (Standard Code Table Pydantic Model)
"""
model_config = ConfigDict(alias_generator=to_camel, from_attributes=True)
id: Optional[str] = Field(default=None, description='标准代码Id')
create_by: Optional[str] = Field(default='', description='创建者')
create_time: Optional[datetime] = Field(default=None, description='创建时间')
update_by: Optional[str] = Field(default='', description='更新者')
update_time: Optional[datetime] = Field(default=None, description='更新时间')
std_num: Optional[str] = Field(default=None, description='标准编号')
std_code: Optional[str] = Field(default=None, description='标准英文名')
std_name: Optional[str] = Field(default=None, description='标准中文名')
std_type: Optional[str] = Field(default=None, description='标准类型(0:基础数据 1:指标数据)')
sys_name: Optional[str] = Field(default=None, description='归属系统')
sys_id: Optional[int] = Field(default=None, description='归属系统Id')
std_menu: Optional[str] = Field(default=None, description='标准业务定义')
code_num: Optional[str] = Field(default=None, description='代码编号')
std_status: Optional[str] = Field(default=None, description='标准状态(1:有效 0:无效)')
buss_dept_id: Optional[int] = Field(default=None, description='业务认责部门')
tech_dept_id: Optional[int] = Field(default=None, description='技术认责部门')
buss_user: Optional[str] = Field(default=None, description='业务认责人员')
tech_user: Optional[str] = Field(default=None, description='技术认责人员')
content_onum: Optional[int] = Field(default=None, description='分类')
std_src: Optional[str] = Field(default=None, description='标准来源')
data_clas: Optional[str] = Field(default=None, description='数据类别')
@as_query
class DataStdMainPageQueryModel(DataStdMainModel):
"""
元数据任务分页查询模型
"""
page_num: int = Field(default=1, description='当前页码')
page_size: int = Field(default=10, description='每页记录数')

420
vue-fastapi-backend/module_admin/service/datastd_service.py

@ -3,10 +3,13 @@ from sqlalchemy.ext.asyncio import AsyncSession
from exceptions.exception import ServiceException
from module_admin.dao.datastd_dao import DataStdDao
from module_admin.entity.vo.common_vo import CrudResponseModel
from module_admin.entity.vo.datastd_vo import DataStdCodeModel,DeleteDataStdModel,DataStdDictModel
from module_admin.entity.vo.datastd_vo import DataStdCodeModel,DeleteDataStdModel,DataStdDictModel,DataStdMainModel
from utils.common_util import CamelCaseUtil
import uuid
from collections import defaultdict
from datetime import datetime
from config.constant import CommonConstant
from module_admin.entity.vo.data_ast_content_vo import DataCatalogPageQueryModel, DeleteDataCatalogModel,DataCatalogResponseWithChildren,DataCatalogMovedRequest,DataCatalogMergeRequest,DataCatalogChild,DataCatalogMoverelRequest
class DataStdService:
"""
@ -392,3 +395,418 @@ class DataStdService:
if dict_type and dict_type.id != id:
return CommonConstant.NOT_UNIQUE
return CommonConstant.UNIQUE
# ----------------------------------------------------------------数据标准分类----------------------------------------------------------------------------------------------------
@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 DataStdDao.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 content_onum, 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[content_onum] = common_fields
# 构建父子关系
root = None
for content_onum, 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 content_onum, 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 get_catalog_detail_services(cls, query_db: AsyncSession, content_onum: int):
"""
获取数据目录详细信息service
:param query_db: orm对象
:param content_onum: 数据目录ID
:return: 数据目录详细信息对象
"""
catalog_detail_result = await DataStdDao.get_catalog_by_id(query_db, content_onum)
return catalog_detail_result
@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 DataStdDao.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 DataStdDao.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)}")
@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 DataStdDao.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 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 content_onum in content_onum_list:
catalog = await cls.get_catalog_detail_services(query_db, int(content_onum))
if not catalog:
raise ServiceException(message=f'目录ID {content_onum} 不存在')
await DataStdDao.delete_catalog_dao(query_db, DeleteDataCatalogModel(content_onums=content_onum))
# await DataStdDao.delete_ast_book_mark_rela_by_content_onum(query_db, int(content_onum), 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 get_data_asset_catalog_tree_services(cls, query_db: AsyncSession):
"""
获取数据资产树信息service
:param query_db: orm对象
:return: 数据资产树信息对象
"""
# 从 DAO 层获取数据
rows = await DataStdDao.get_data_asset_catalog_tree(query_db)
# 使用字典暂存分组数据
sys_groups = {}
for item in rows:
sys_name, eng_name, cn_name, ast_no = item
# 创建或获取系统分组
if sys_name not in sys_groups:
sys_groups[sys_name] = {
"dataAssetSysName": sys_name,
"children": []
}
# 添加子节点
sys_groups[sys_name]["children"].append({
"dataAssetCatalogNo": eng_name,
"dataAssetCatalogName": cn_name,
"dataAssetCatalogAstno": ast_no
})
results = list(sys_groups.values())
# 转换为最终列表格式
return results
@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 DataStdDao.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 DataStdDao.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 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 DataStdDao.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 moverel_data_ast_catalog_services(cls, query_db: AsyncSession, request: DataCatalogMoverelRequest):
"""
移动数据目录service
"""
moverel_catalog_data = {
'rela_onum': request.rela_onum,
'content_onum': request.content_onum,
'content_onum_after': request.content_onum_after
}
try:
await DataStdDao.moverel_data_ast_catalog_dao(query_db, moverel_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 check_std_num_unique(cls, query_db: AsyncSession, model: DataStdMainModel):
"""
校验标准编号是否唯一
"""
id = '-1' if model.id is None else model.id
check_model = DataStdMainModel()
check_model.std_num=model.std_num
existing = await DataStdDao.get_data_main_by_info(query_db, check_model)
return CommonConstant.NOT_UNIQUE if existing and existing.id != id else CommonConstant.UNIQUE
@classmethod
async def get_std_main_list(cls, query_db: AsyncSession, query_object: DataStdMainModel, is_page: bool = False):
return await DataStdDao.get_std_main_list(query_db, query_object, is_page)
@classmethod
async def get_std_main_by_id(cls, query_db: AsyncSession, id: str):
mainstd= await DataStdDao.get_std_main_by_id(query_db, id)
if mainstd:
return DataStdMainModel(**CamelCaseUtil.transform_result(mainstd))
else:
return DataStdMainModel(**dict())
@classmethod
async def add_std_main(cls, query_db: AsyncSession, model: DataStdMainModel):
if not await cls.check_std_num_unique(query_db, model):
raise ServiceException(message=f"标准编号 {model.std_num} 已存在")
model.id=str(uuid.uuid4())
await DataStdDao.add_std_main(query_db, model)
return CrudResponseModel(is_success=True, message='新增标准成功')
@classmethod
async def edit_std_main(cls, query_db: AsyncSession, model: DataStdMainModel):
if not await cls.check_std_num_unique(query_db, model):
raise ServiceException(message=f"标准编号 {model.std_num} 已存在")
existing = await cls.get_std_main_by_id(query_db, model.id)
if existing:
await DataStdDao.update_std_main(query_db, model.model_dump(exclude_unset=True))
return CrudResponseModel(is_success=True, message='编辑标准成功')
else:
raise ServiceException(message=f'标准 {model.id} 不存在')
@classmethod
async def delete_std_main(cls, query_db: AsyncSession, ids: str):
if ids:
col_id_list = ids.split(',')
try:
for col_id in col_id_list:
col_info = await cls.get_std_main_by_id(query_db, col_id)
if col_info:
# 校验不能删除的系统内置列
await DataStdDao.delete_std_main(query_db, col_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为空')

110
vue-fastapi-frontend/src/api/datastd/directory.js

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

50
vue-fastapi-frontend/src/api/datastd/std.js

@ -174,4 +174,54 @@ export function deleteStdDicts(colIds) {
method: 'delete'
})
}
// 查询数据标准列表
export function listStdMain(query) {
return request({
url: '/default-api/datastd/stdmain/main/list',
method: 'get',
params: query
})
}
// 查询数据标准详情
export function getStdMain(colId) {
return request({
url: '/default-api/datastd/stdmain/main/' + parseStrEmpty(colId),
method: 'get'
})
}
// 新增数据标准
export function addStdMain(data) {
return request({
url: '/default-api/datastd/stdmain/main',
method: 'post',
data: data
})
}
// 修改数据标准
export function updateStdMain(data) {
return request({
url: '/default-api/datastd/stdmain/main',
method: 'put',
data: data
})
}
// 删除数据标准
export function deleteStdMain(colId) {
return request({
url: '/default-api/datastd/stdmain/main/' + colId,
method: 'delete'
})
}

203
vue-fastapi-frontend/src/views/datastd/main/components/AddEditForm.vue

@ -0,0 +1,203 @@
<template>
<el-dialog width="500px" append-to-body :title="isEdit ? '修改数据标准' : '新增数据标准'" v-model="visible" @close="handleClose">
<el-form :model="formData" ref="formRef" label-width="120px" :rules="formRules">
<el-form-item label="标准编号" prop="stdNum">
<el-input v-model="formData.stdNum" :disabled="isEdit" placeholder="请输入标准编号" clearable />
</el-form-item>
<el-form-item label="标准中文名" prop="stdName">
<el-input v-model="formData.stdName" placeholder="请输入标准中文名" clearable />
</el-form-item>
<el-form-item label="标准英文名" prop="stdCode">
<el-input v-model="formData.stdCode" placeholder="请输入标准英文名" clearable />
</el-form-item>
<el-form-item label="标准业务定义" prop="stdMenu">
<el-input v-model="formData.stdMenu" placeholder="请输入标准业务定义" clearable />
</el-form-item>
<el-form-item label="标准类型" prop="stdType">
<el-select v-model="formData.stdType" placeholder="请输入标准类型">
<el-option label="基础数据" value="0" />
<el-option label="指标数据" value="1" />
</el-select>
</el-form-item>
<el-form-item label="标准来源" prop="stdSrc">
<el-select v-model="formData.stdSrc" placeholder="请选择标准来源">
<el-option label="行业标准" value="行业标准" />
<el-option label="自建标准" value="自建标准" />
</el-select>
</el-form-item>
<el-form-item label="数据类别" prop="dataClas">
<el-select v-model="formData.dataClas" placeholder="请选择数据类别">
<el-option label="日期类" value="日期类" />
<el-option label="文本类" value="文本类" />
<el-option label="数值类" value="数值类" />
<el-option label="金额类" value="金额类" />
<el-option label="编码类" value="编码类" />
<el-option label="标志类" value="标志类" />
<el-option label="码值类" value="码值类" />
</el-select>
</el-form-item>
<el-form-item label="代码编号" prop="codeNum">
<el-input v-model="formData.codeNum" placeholder="请输入代码编号" clearable />
</el-form-item>
<el-form-item label="业务认责部门" prop="bussDeptId">
<el-tree-select
v-model="formData.bussDeptId"
:data="deptOptions"
:props="{ value: 'id', label: 'label', children: 'children' }"
value-key="id"
placeholder="请选择业务认责部门"
check-strictly />
</el-form-item>
<el-form-item label="业务认责人员" prop="bussUser">
<el-select v-model="formData.bussUser" placeholder="请选择业务认责人员">
<el-option
v-for="dict in userList"
:key="dict.id"
:label="dict.userName"
:value="dict.userName"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="技术认责部门" prop="techDeptId">
<el-tree-select
v-model="formData.techDeptId"
:data="deptOptions"
:props="{ value: 'id', label: 'label', children: 'children' }"
value-key="id"
placeholder="请选择技术认责部门"
check-strictly />
</el-form-item>
<el-form-item label="技术认责人员" prop="techUser">
<el-select v-model="formData.techUser" placeholder="技术认责人员">
<el-option
v-for="dict in userList"
:key="dict.id"
:label="dict.userName"
:value="dict.userName"
></el-option>
</el-select>
</el-form-item>
<!-- 底部按钮区域 -->
<el-row justify="center" style="margin-top: 20px;">
<el-col :span="4" style="padding-right: 10px;">
<el-button @click="handleClose" style="width: 100%" plain>取消</el-button>
</el-col>
<el-col :span="4" style="padding-left: 10px;">
<el-button type="primary" @click="handleSubmit" style="width: 100%">保存</el-button>
</el-col>
</el-row>
</el-form>
</el-dialog>
</template>
<script setup>
import { ref, watch } from 'vue';
import { updateStdMain, addStdMain } from '@/api/datastd/std'; //
import { listUser, deptTreeSelect } from "@/api/system/user";
const { proxy } = getCurrentInstance();
const { std_code_status,std_code_appr } = proxy.useDict("std_code_status","std_code_appr");
const props = defineProps({
data: {
type: Object,
required: false,
},
isEdit: {
type: Boolean,
},
dbResourceOldList: {
type: Object,
},
visible: {
type: Boolean,
},
});
//
const formRules = ref({
stdNum: [{ required: true, message: '请输入标准编号', trigger: 'blur' }],
stdType: [{ required: true, message: '请选择标准类型', trigger: 'change' }],
stdSrc: [{ required: true, message: '请选择标准来源', trigger: 'change' }],
dataClas: [{ required: true, message: '请选择数据类别', trigger: 'change' }],
bussDeptId: [{ required: true, message: '请选择业务认责部门', trigger: 'blur' }],
techDeptId: [{ required: true, message: '请选择技术认责部门', trigger: 'blur' }],
bussUser: [{ required: true, message: '请输入业务认责人', trigger: 'blur' }],
techUser: [{ required: true, message: '请输入技术认责人', trigger: 'blur' }],
});
const showSys = ref(false);
const emit = defineEmits(['update:visible', 'refresh']);
const userList = ref([]);
const formData = ref({ ...props.data });
const visible = ref(props.visible); // 使 prop visible
function dataChange(data) {
// dbResourceOldList name
const selectedItem = props.dbResourceOldList.find(item => item.id === data);
if (selectedItem) {
// name formData.value.dbRName
formData.value.sysName = selectedItem.name;
} else {
// formData.value.dbRName
formData.value.sysName = '';
}
}
// props.visible local visible
watch(() => props.visible, (newVal) => {
visible.value = newVal;
formData.value = { ...props.data }
});
function getList() {
listUser({pageSize:1000,pageNum:1}).then(res => {
userList.value = res.rows;
});
};
const handleClose = () => {
emit('update:visible', false); //
};
const deptOptions = ref(undefined);
function getDeptTree() {
deptTreeSelect().then(response => {
deptOptions.value = response.data;
});
};
function changeCodeType(data) {
if (data != "company") {
showSys.value = true;
formData.value.sysName = "";
formData.value.sysId = undefined;
} else {
showSys.value = false;
formData.value.sysName = "公司级";
formData.value.sysId = 10000;
}
}
getDeptTree();
getList();
const handleSubmit = () => {
const formRef = proxy.$refs.formRef;
formRef.validate((valid) => {
if (valid) {
const apiCall = props.isEdit ? updateStdMain(formData.value) : addStdMain(formData.value);
apiCall
.then((response) => {
console.log(response.success,"sssssssss")
if (response.success) {
emit('refresh');
handleClose();
} else {
proxy.$message.error(response.data || '操作失败,请稍后重试');
}
})
} else {
console.log('表单验证失败');
return false;
}
});
};
</script>

171
vue-fastapi-frontend/src/views/datastd/main/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/datastd/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/datastd/main/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/datastd/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/datastd/main/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/datastd/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/datastd/main/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/datastd/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>

651
vue-fastapi-frontend/src/views/datastd/main/index.vue

@ -0,0 +1,651 @@
<template>
<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-form :model="queryParams" ref="queryRef" :inline="true">
<el-form-item label="标准编号/名称">
<el-input v-model="queryParams.stdNum" placeholder="请输入标准编号" />
</el-form-item>
<el-form-item label="业务定义">
<el-input v-model="queryParams.stdMenu" placeholder="请输入业务定义" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 操作按钮 -->
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="Plus"
@click="handleAdd"
v-hasPermi="['meta:metaSecurityCol:add']"
>新增</el-button
>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="Edit"
:disabled="single"
@click="handleEdit"
v-hasPermi="['meta:metaSecurityCol:edit']"
>修改</el-button
>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Delete"
:disabled="multiple"
@click="handleRemove"
v-hasPermi="['meta:metaSecurityCol:remove']"
>删除</el-button
>
</el-col>
</el-row>
<!-- 表格展示 -->
<el-table
v-loading="loading"
:data="tableData"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="标准编号" prop="stdNum" width="150"></el-table-column>
<el-table-column label="标准英文名" prop="stdCode" width="150"></el-table-column>
<el-table-column label="标准中文名" prop="stdName" width="150"></el-table-column>
<el-table-column label="标准业务定义" prop="stdMenu" width="150"></el-table-column>
<el-table-column label="类型" prop="stdType" width="150"></el-table-column>
<el-table-column label="标准来源" prop="stdSrc" width="150"></el-table-column>
<el-table-column label="数据类别" prop="dataClas" width="150"></el-table-column>
<el-table-column label="代码编号" prop="codeNum" width="150"></el-table-column>
<el-table-column label="业务认责部门" prop="bussDeptId" width="150"></el-table-column>
<el-table-column label="业务认责人员" prop="bussUser" width="150"></el-table-column>
<el-table-column label="技术认责部门" prop="techDeptId" width="150"></el-table-column>
<el-table-column label="技术认责人员" prop="techUser" width="150"></el-table-column>
<!-- <el-table-column label="分类" prop="contentOnum" width="150"></el-table-column> -->
<el-table-column label="更新时间" prop="updateTime" width="180"></el-table-column>
<el-table-column label="操作" align="center" width="180">
<template #default="scope">
<el-button
@click="handleEdit(scope.row)"
type="text"
icon="Edit"
/>
<el-button
@click="handleRemove(scope.row)"
type="text"
icon="Delete"
/>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="handlePagination"
/>
</el-col>
</el-row>
<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"
/>
<AddEditForm
:data="selectedRow"
:isEdit="isEdit"
:dbResourceOldList="dbResourceOldList"
v-model:visible="dialogVisible"
@refresh="getList"
/>
</div>
</template>
<script setup name="Directory">
import { ElMessage, ElMessageBox } from 'element-plus'
import {
getDirectoryTree,
delDirectory,
delDirectoryAsset,
addDirectoryCollection,
cancelDirectoryCollection,
} from '@/api/datastd/directory'
import auth from '@/plugins/auth'
import FormDialog from './components/FormDialog.vue'
import MoveDialog from './components/MoveDialog.vue'
import MergerDialog from './components/MergerDialog.vue'
import AssetMoveDialog from './components/AssetMoveDialog.vue'
import AddEditForm from "./components/AddEditForm.vue";
import {
listStdMain,
getStdMain,
deleteStdMain,
} from "@/api/datastd/std"; //
import useUserStore from '@/store/modules/user'
import { nextTick } from 'vue'
import { datasourcetree } from "@/api/meta/metatask";
const { proxy } = getCurrentInstance()
const { hasPermiOr } = auth
const userStore = useUserStore()
const defaultProps = {
children: 'children',
label: 'contentName',
}
const directoryTree = ref([])
const currentNode = ref({})
const directoryTableData = ref([])
const queryParams = ref({
stdNum: '',
stdMenu: '',
pageNum: 1,
pageSize: 10,
});
const single = ref(true);
const multiple = ref(true);
const dialogVisible = ref(false);
const selectedRow = ref(null);
const isEdit = ref(false);
const tableData = ref([]);
const total = ref(0);
const loading = ref(false);
const ids = ref([]);
const stdNums = ref([]);
const handlePagination = (pageNum, pageSize) => {
queryParams.value.pageNum = pageNum;
queryParams.value.pageSize = pageSize;
handleQuery();
};
const resetQuery = () => {
queryParams.value = { stdNum: '', stdMenu: '' , pageNum: 1,
pageSize: 10}
handleQuery()
}
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
const handleSelectionChange = (selection) => {
single.value = selection.length !== 1;
multiple.value = !selection.length;
ids.value = selection.map((item) => item.id);
stdNums.value = selection.map((item) => item.stdNum);
};
const setDirectoryTree = () => {
return getDirectoryTree({
pageSize: 999,
}).then(({ rows }) => {
directoryTree.value = addTreeNodeId(rows)
})
}
setDirectoryTree().then(async () => {
if (directoryTree.value.length) {
currentNode.value = directoryTree.value[0]
directoryTableData.value = directoryTree.value[0].children || []
}
})
const getList = async () => {
loading.value = true;
const response = await listStdMain(queryParams.value);
tableData.value = response.rows;
total.value = response.total;
loading.value = false;
};
const handleRemove = (row) => {
const idsToDelete = row.id ? [row.id] : ids.value;
const codesToDelete = row.stdNum ? [row.stdNum] : stdNums.value;
proxy.$modal
.confirm(
'是否确认删除标准编号为"' + codesToDelete.toString() + '"的数据项?'
)
.then(function () {
return deleteStdMain(idsToDelete.toString());
})
.then(() => {
handleQuery();
proxy.$modal.msgSuccess("删除成功");
})
.catch(() => {});
};
const dbResourceOldList = ref([]);
const handleAdd = () => {
console.log("update:visible", 111);
isEdit.value = false;
selectedRow.value = {
stdType: "",
stdNum: "",
stdCode: "",
stdName: "",
stdMenu: "",
dataType: "",
stdCode: "",
bussDeptId: "",
bussUser: "",
techDeptId: "",
techUser: "",
};
//
dialogVisible.value = true;
};
const handleEdit = (row) => {
const id = row.id ? row.id : ids.value.toString();
getStdMain(id).then((response) => {
selectedRow.value = response.data;
isEdit.value = true;
dialogVisible.value = true;
});
};
/** 增加临时ID作为树节点的唯一键值 */
const addTreeNodeId = (tree) => {
return tree.map((node) => {
return {
...node,
tempId: node.astOnum || node.contentOnum,
children:
node.children && node.children.length
? addTreeNodeId(node.children)
: [],
}
})
}
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) => {
return data.contentOnum === 1
}
//
const isCollectionDirectory = (data) => {
return data.contentName === '临时'
}
//
const isCollection = (data) => {
return false
}
//
const isCollected = (data) => {
return data.bookmarkFlag === 1
}
//
const isDirectory = (data) => {
return data.contentOnum && !isRoot(data) && !data.astOnum
}
//
const isAsset = (data) => {
return data.astOnum
}
const activeName = ref('1')
const handleNodeClick = async (data) => {
if (isCollectionDirectory(data)) {
return
}
}
const handleCollect = (data, e) => {
e.stopPropagation()
addDirectoryCollection({
dataAstNo: String(data.dataAstNo),
userId: String(userStore.id),
}).then(() => {
proxy.$modal.msgSuccess('收藏成功')
setDirectoryTree()
})
}
const handleCollectionCancel = (data, e) => {
e.stopPropagation()
cancelDirectoryCollection(data.relaOnum).then(() => {
proxy.$modal.msgSuccess('取消成功')
setDirectoryTree()
})
}
const formDialogRef = ref(null)
const handleAddDialogOpen = (data) => {
formDialogRef.value.title = '新增分类'
formDialogRef.value.openDialog({
suprContentOnum: data.contentOnum,
})
}
const handleEditDialogOpen = (data) => {
formDialogRef.value.title = '修改分类'
formDialogRef.value.openDialog(data)
}
const handleDelete = (data) => {
ElMessageBox.confirm(
`确定删除 ${data.contentName} 分类吗?`,
'分类删除',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
).then(() => {
delDirectory(data.contentOnum).then(() => {
proxy.$modal.msgSuccess('删除成功')
setDirectoryTree()
})
})
}
const moveDialogRef = ref(null)
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 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 handleCommand = (command, data) => {
const strategy = {
handleAddDialogOpen: handleAddDialogOpen,
handleEditDialogOpen: handleEditDialogOpen,
handleDelete: handleDelete,
handleMoveDialogOpen: handleMoveDialogOpen,
handleMergerDialogOpen: handleMergerDialogOpen,
handleAssetDelete: handleAssetDelete,
handleAssetMoveDialogOpen: handleAssetMoveDialogOpen,
}
strategy[command](data)
}
onMounted(() => {
datasourcetree().then((response) => {
dbResourceOldList.value = response.rows;
});
getList();
});
</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>

269
vue-fastapi-frontend/src/views/datastd/stddict/index.vue

@ -35,7 +35,12 @@
<el-col :span="20" :xs="24">
<el-form :model="queryParams" ref="queryRef" :inline="true">
<el-form-item label="字典编号" prop="dictNum">
<el-input v-model="queryParams.dictNum" placeholder="请输入标准字典编号" clearable style="width: 220px" />
<el-input
v-model="queryParams.dictNum"
placeholder="请输入标准字典编号"
clearable
style="width: 220px"
/>
</el-form-item>
<el-form-item>
@ -53,7 +58,8 @@
icon="Plus"
@click="handleAdd"
v-hasPermi="['meta:metaSecurityCol:add']"
>新增</el-button>
>新增</el-button
>
</el-col>
<el-col :span="1.5">
<el-button
@ -63,7 +69,8 @@
:disabled="single"
@click="handleEdit"
v-hasPermi="['meta:metaSecurityCol:edit']"
>修改</el-button>
>修改</el-button
>
</el-col>
<el-col :span="1.5">
<el-button
@ -73,28 +80,57 @@
:disabled="multiple"
@click="handleRemove"
v-hasPermi="['meta:metaSecurityCol:remove']"
>删除</el-button>
>删除</el-button
>
</el-col>
</el-row>
<!-- 表格展示 -->
<el-table v-loading="loading" :data="tableData" @selection-change="handleSelectionChange">
<el-table
v-loading="loading"
:data="tableData"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="归属" align="center" width="200">
<template #default="{ row }">
{{ row.dictLevel === 'company' ? '公司级' : '系统级('+row.sysName+')' }}
</template>
</el-table-column>
<el-table-column label="类型" align="center">
<template #default="{ row }">
{{ row.dictType == 0 ? '基础数据' : '指标数据' }}
</template>
</el-table-column>
<el-table-column label="归属" align="center" width="200">
<template #default="{ row }">
{{
row.dictLevel === "company"
? "公司级"
: "系统级(" + row.sysName + ")"
}}
</template>
</el-table-column>
<el-table-column label="类型" align="center">
<template #default="{ row }">
{{ row.dictType == 0 ? "基础数据" : "指标数据" }}
</template>
</el-table-column>
<!-- <el-table-column label="来源系统" width="150" align="center" prop="sysName" /> -->
<el-table-column label="字典编号" width="150" align="center" prop="dictNum" />
<el-table-column label="字典英文名" width="120" align="center" prop="dictCode" />
<el-table-column label="字典中文名" width="120" align="center" prop="dictName" />
<el-table-column label="字典业务定义" width="120" align="center" prop="dictMenu" />
<el-table-column
label="字典编号"
width="150"
align="center"
prop="dictNum"
/>
<el-table-column
label="字典英文名"
width="120"
align="center"
prop="dictCode"
/>
<el-table-column
label="字典中文名"
width="120"
align="center"
prop="dictName"
/>
<el-table-column
label="字典业务定义"
width="120"
align="center"
prop="dictMenu"
/>
<el-table-column label="数据类型" align="center" prop="dataType" />
<el-table-column label="数据标准" align="center" prop="stdCode" />
<el-table-column label="字典状态" align="center" prop="dictStatus">
@ -105,52 +141,104 @@
/>
</template>
</el-table-column>
<el-table-column label="业务认责部门" width="120" align="center" prop="bussDeptName" />
<el-table-column label="业务认责人员" width="120" align="center" prop="bussUser" />
<el-table-column label="技术认责部门" width="120" align="center" prop="techDeptName" />
<el-table-column label="技术认责人员" width="120" align="center" prop="techUser" />
<el-table-column label="更新者" width="120" align="center" prop="updateBy" />
<el-table-column label="更新时间" width="120" align="center" prop="updateTime" />
<el-table-column
label="业务认责部门"
width="120"
align="center"
prop="bussDeptName"
/>
<el-table-column
label="业务认责人员"
width="120"
align="center"
prop="bussUser"
/>
<el-table-column
label="技术认责部门"
width="120"
align="center"
prop="techDeptName"
/>
<el-table-column
label="技术认责人员"
width="120"
align="center"
prop="techUser"
/>
<el-table-column
label="更新者"
width="120"
align="center"
prop="updateBy"
/>
<el-table-column
label="更新时间"
width="120"
align="center"
prop="updateTime"
/>
<el-table-column label="操作" align="center" width="180">
<template #default="scope">
<el-button @click="handleEdit(scope.row)" type="text" icon="Edit" />
<el-button @click="handleRemove(scope.row)" type="text" icon="Delete" />
<el-button
@click="handleEdit(scope.row)"
type="text"
icon="Edit"
/>
<el-button
@click="handleRemove(scope.row)"
type="text"
icon="Delete"
/>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="handlePagination" />
<pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="handlePagination"
/>
</el-col>
</el-row>
<AddEditForm
:data="selectedRow"
:isEdit="isEdit"
:dbResourceOldList="dbResourceOldList"
v-model:visible="dialogVisible"
@refresh="getList"
/>
:data="selectedRow"
:isEdit="isEdit"
:dbResourceOldList="dbResourceOldList"
v-model:visible="dialogVisible"
@refresh="getList"
/>
</div>
</template>
<script setup>
import { ref, reactive, onMounted, toRefs } from 'vue';
import { listStdDict, addStdDict, getStdDict, updateStdDict, deleteStdDict } from "@/api/datastd/std"; //
import { ref, reactive, onMounted, toRefs } from "vue";
import {
listStdDict,
addStdDict,
getStdDict,
updateStdDict,
deleteStdDict,
} from "@/api/datastd/std"; //
import { datasourcetree } from "@/api/meta/metatask";
import AddEditForm from './AddEditForm.vue';
import AddEditForm from "./AddEditForm.vue";
const { proxy } = getCurrentInstance();
const { std_code_status,std_code_appr } = proxy.useDict("std_code_status","std_code_appr");
const { std_code_status, std_code_appr } = proxy.useDict(
"std_code_status",
"std_code_appr"
);
const queryParams = ref({
dictNum: '',
dictName: '',
dictType: '',
sysName: '',
classId: 'dict',
sysId: '',
dictNum: "",
dictName: "",
dictType: "",
sysName: "",
classId: "dict",
sysId: "",
pageNum: 1,
pageSize: 10
pageSize: 10,
});
const single = ref(true);
const multiple = ref(true);
@ -186,9 +274,8 @@ const handleNodeClick = (data) => {
const handleSelectionChange = (selection) => {
single.value = selection.length !== 1;
multiple.value = !selection.length;
ids.value = selection.map(item => item.id);
codeNums.value = selection.map(item => item.dictNum);
ids.value = selection.map((item) => item.id);
codeNums.value = selection.map((item) => item.dictNum);
};
const getList = async () => {
@ -206,13 +293,13 @@ const handleQuery = () => {
const resetQuery = () => {
queryParams.value = {
dictNum: '',
dictName: '',
dictType: '',
sysName: '',
dictNum: "",
dictName: "",
dictType: "",
sysName: "",
sysId: undefined,
pageNum: 1,
pageSize: 10
pageSize: 10,
};
getList();
};
@ -220,54 +307,68 @@ const resetQuery = () => {
const handleRemove = (row) => {
const idsToDelete = row.id ? [row.id] : ids.value;
const codesToDelete = row.codeNum ? [row.codeNum] : codeNums.value;
proxy.$modal.confirm('是否确认删除字典编号为"' + codesToDelete.toString() + '"的数据项?').then(function () {
return deleteStdDict(idsToDelete.toString());
}).then(() => {
handleQuery();
proxy.$modal.msgSuccess("删除成功");
}).catch(() => {});
proxy.$modal
.confirm(
'是否确认删除字典编号为"' + codesToDelete.toString() + '"的数据项?'
)
.then(function () {
return deleteStdDict(idsToDelete.toString());
})
.then(() => {
handleQuery();
proxy.$modal.msgSuccess("删除成功");
})
.catch(() => {});
};
const dbResourceOldList = ref([]);
const handleAdd = () => {
console.log('update:visible', 111)
console.log("update:visible", 111);
isEdit.value = false;
selectedRow.value={
dictLevel: 'company',
sysId: 10000,
sysName: "公司级",
dictType: '',
dictNum: '',
dictCode: '',
dictName: '',
dictMenu: '',
dataType: '',
stdCode: '',
bussDeptId: '',
bussUser: '',
techDeptId: '',
techUser: ''
}
selectedRow.value = {
dictLevel: "company",
sysId: 10000,
sysName: "公司级",
dictType: "",
dictNum: "",
dictCode: "",
dictName: "",
dictMenu: "",
dataType: "",
stdCode: "",
bussDeptId: "",
bussUser: "",
techDeptId: "",
techUser: "",
};
//
dialogVisible.value = true;};
dialogVisible.value = true;
};
const handleEdit = (row) => {
const id = row.id ?row.id: ids.value.toString()
getStdDict(id).then(response => {
const id = row.id ? row.id : ids.value.toString();
getStdDict(id).then((response) => {
selectedRow.value = response.data;
isEdit.value = true;
dialogVisible.value = true;
});
}
};
onMounted(() => {
datasourcetree().then(response => {
datasourcetree().then((response) => {
dbResourceOldList.value = response.rows;
dbResourceOptions.value = [
{ id: 10000, name: "公司级字典", parentId: 0, children: [] },
{ id: 99999, name: "系统级字典", parentId: 0, children: response.rows.map(element => ({ ...element, parentId: "99999" })) }
{
id: 99999,
name: "系统级字典",
parentId: 0,
children: response.rows.map((element) => ({
...element,
parentId: "99999",
})),
},
];
});
getList();

Loading…
Cancel
Save