Browse Source

Merge remote-tracking branch 'origin/master'

master^2
xueyinfei 4 days ago
parent
commit
56dcbd9f00
  1. 2
      vue-fastapi-backend/module_admin/dao/metadata_config_dao.py
  2. 1
      vue-fastapi-backend/module_admin/entity/do/metadata_config_do.py
  3. 1
      vue-fastapi-backend/module_admin/entity/vo/metadata_config_vo.py
  4. 6
      vue-fastapi-backend/module_admin/service/datastd_service.py
  5. 192
      vue-fastapi-backend/module_admin/service/metasecurity_service.py
  6. 201
      vue-fastapi-frontend/src/views/dataAsset/assetDetail/index.vue
  7. 7
      vue-fastapi-frontend/src/views/dataAsset/directory/components/FormDialog.vue
  8. 5
      vue-fastapi-frontend/src/views/meta/metatask/index.vue
  9. 49
      vue-fastapi-frontend/src/views/metadataConfig/bizPermiConfig/index.vue

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

@ -282,7 +282,7 @@ class MetadataConfigDao:
SecuBizPermiConfig.update_by, SecuBizPermiConfig.update_by,
SecuBizPermiConfig.update_time, SecuBizPermiConfig.update_time,
SecuBizConfig.biz_name, SecuBizConfig.biz_name,
MetadataSec.sec_level_summary SecuBizPermiConfig.sec_level_summary
) )
.join(SecuBizConfig, SecuBizPermiConfig.biz_onum == SecuBizConfig.onum, isouter=True) .join(SecuBizConfig, SecuBizPermiConfig.biz_onum == SecuBizConfig.onum, isouter=True)
.join(MetadataSec, SecuBizConfig.risk_lvl == MetadataSec.onum, isouter=True) .join(MetadataSec, SecuBizConfig.risk_lvl == MetadataSec.onum, isouter=True)

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

@ -73,6 +73,7 @@ class SecuBizPermiConfig(Base):
create_time = Column(DateTime, nullable=True, comment="创建时间") create_time = Column(DateTime, nullable=True, comment="创建时间")
update_by = Column(String(20), nullable=True, comment="更新者") update_by = Column(String(20), nullable=True, comment="更新者")
update_time = Column(DateTime, nullable=True, comment="更新时间") update_time = Column(DateTime, nullable=True, comment="更新时间")
sec_level_summary = Column(String(200), comment='等级简介')
class SecuBizConfig(Base): class SecuBizConfig(Base):

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

@ -219,6 +219,7 @@ class SecuBizPermiConfigModel(BaseModel):
create_time: Optional[datetime] = Field(default=None, description='创建时间') create_time: Optional[datetime] = Field(default=None, description='创建时间')
update_by: Optional[str] = Field(default=None, description='更新者') update_by: Optional[str] = Field(default=None, description='更新者')
update_time: Optional[datetime] = Field(default=None, description='更新时间') update_time: Optional[datetime] = Field(default=None, description='更新时间')
sec_level_summary: Optional[str] = Field(default=None, description='等级简介')
class SecuBizPermiConfigBatchModel(BaseModel): class SecuBizPermiConfigBatchModel(BaseModel):

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

@ -41,6 +41,12 @@ class DataStdService:
:param is_page: 是否开启分页 :param is_page: 是否开启分页
:return: 列配置列表信息对象 :return: 列配置列表信息对象
""" """
if query_object.src_sys==10000:
query_object.src_sys = None
query_object.cd_type ='company'
if query_object.src_sys==99999:
query_object.src_sys = None
query_object.cd_type ='sys'
col_list_result = await DataStdDao.get_std_code_list(query_db, query_object, is_page) col_list_result = await DataStdDao.get_std_code_list(query_db, query_object, is_page)
return col_list_result return col_list_result
# @classmethod # @classmethod

192
vue-fastapi-backend/module_admin/service/metasecurity_service.py

@ -17,7 +17,9 @@ from sqlalchemy.exc import OperationalError
import json import json
import re import re
from decimal import Decimal from decimal import Decimal
import sqlparse
from sqlparse.sql import Identifier, IdentifierList, Function, Token
from sqlparse.tokens import Keyword, DML
class MetaSecurityService: class MetaSecurityService:
""" """
数据源安全管理模块服务层 数据源安全管理模块服务层
@ -304,7 +306,7 @@ class MetaSecurityService:
dbConnent= cls.get_db_engine(dsDataResource["type"],dsDataResource["connectionParams"]) dbConnent= cls.get_db_engine(dsDataResource["type"],dsDataResource["connectionParams"])
# await test_connection(dbConnent) # await test_connection(dbConnent)
#3获取sql中涉及的表名 #3获取sql中涉及的表名
sqlScheamAndTable =await cls.get_tables_from_sql(page_object.sqlStr) sqlScheamAndTable =await get_tables_from_sql(page_object.sqlStr)
oldStrSql=generate_pagination_sql(page_object,dsDataResource["type"]) oldStrSql=generate_pagination_sql(page_object,dsDataResource["type"])
#4.执行原始sql #4.执行原始sql
result = await cls.execute_sql(dbConnent, oldStrSql,"原始") result = await cls.execute_sql(dbConnent, oldStrSql,"原始")
@ -405,74 +407,6 @@ class MetaSecurityService:
except SQLAlchemyError as e: except SQLAlchemyError as e:
raise RuntimeError(f"{sql_type}执行 SQL 查询时发生错误: {e}") raise RuntimeError(f"{sql_type}执行 SQL 查询时发生错误: {e}")
# async def get_tables_from_sql(sql_query: str):
# """
# 解析 SQL 查询,提取所有 Schema 和 Table 名称,并确保表名包含模式名(schema.table)。
# :param sql_query: SQL 查询字符串
# :return: {'schemas': [...], 'table_names': [...]}
# :raises ServiceException: 如果 SQL 未使用 schema.table 结构,则抛出异常
# """
# # ✅ 改进正则:支持 `FROM a.o, b.x JOIN c.y`
# table_section_pattern = r"(?i)(?:FROM|JOIN|INTO|UPDATE)\s+([\w\.\s,]+)"
# table_sections = re.findall(table_section_pattern, sql_query, re.DOTALL)
# if not table_sections:
# raise ServiceException(data='', message='SQL 解析失败,未找到表名')
# # 解析多个表(用 `,` 和 `JOIN` 拆分)
# for section in table_sections:
# tables = re.split(r"\s*,\s*|\s+JOIN\s+", section, flags=re.IGNORECASE)
# for table in tables:
# table = table.strip().split()[0] # 取 `schema.table`,忽略别名
# if "." not in table:
# raise ServiceException(
# data='',
# message=f"SQL 中的表名必须携带模式名(schema.table),但发现了无模式的表:{table}"
# )
# return table_sections
async def get_tables_from_sql(sql_query: str):
"""
解析 SQL 查询提取所有 schema.table 名称支持嵌套子查询别名JOININTOUPDATE
自动排除字段引用与无模式表
"""
# 1️⃣ 清理注释与多余空白
sql_query = re.sub(r"--.*?$", "", sql_query, flags=re.MULTILINE)
sql_query = re.sub(r"/\*.*?\*/", "", sql_query, flags=re.DOTALL)
sql_query = " ".join(sql_query.split())
# 2️⃣ 匹配 FROM/JOIN/INTO/UPDATE 后面的 schema.table
pattern = re.compile(
r"""(?ix)
(?:FROM|JOIN|INTO|UPDATE)\s+ # SQL 关键字
(?!\() # 排除子查询
(?P<schema>["'`]?[A-Za-z_][\w\$]*["'`]?) # schema
\. # .
(?P<table>["'`]?[A-Za-z_][\w\$]*["'`]?) # table
\b
""",
re.VERBOSE
)
# 3️⃣ 使用 finditer,逐个安全提取匹配项
table_names = set()
for m in pattern.finditer(sql_query):
schema_raw = m.group("schema")
table_raw = m.group("table")
if not schema_raw or not table_raw:
continue
schema =unquote_ident(schema_raw)
table = unquote_ident(table_raw)
table_names.add(f"{schema}.{table}")
# 4️⃣ 检查结果
if not table_names:
raise ServiceException(data='', message="SQL 解析失败,未找到任何 schema.table 结构")
return list(table_names)
@classmethod @classmethod
async def get_columns_from_tables(cls, dbConnent, table_names, db_type: str): async def get_columns_from_tables(cls, dbConnent, table_names, db_type: str):
@ -734,25 +668,25 @@ async def replace_table_with_subquery(ctrSqlDict, oldStrSql):
original_table = match.group(2) original_table = match.group(2)
alias_part = match.group(3) # " AS xxx" 或 " xxx" alias_part = match.group(3) # " AS xxx" 或 " xxx"
alias_name = match.group(4) # xxx alias_name = match.group(4) # xxx
sql_keywords = {
"SELECT", "INSERT", "UPDATE", "DELETE", "MERGE", "TRUNCATE",
"VALUES", "RETURNING", "FROM", "WHERE", "GROUP", "HAVING", "ORDER",
"LIMIT", "OFFSET", "DISTINCT", "ALL", "UNION", "INTERSECT", "EXCEPT",
"JOIN", "INNER", "LEFT", "RIGHT", "FULL", "CROSS", "NATURAL", "USING", "ON",
"TABLE", "VIEW", "INDEX", "PRIMARY", "KEY", "FOREIGN", "REFERENCES", "NOT",
"NULL", "UNIQUE", "CHECK", "DEFAULT", "IF", "ELSE", "CASE", "WHEN", "THEN",
"END", "LOOP", "FOR", "WHILE", "CREATE", "ALTER", "DROP", "TRUNCATE", "COMMENT",
"EXISTS", "IN", "IS", "LIKE", "ILIKE", "SIMILAR", "BETWEEN", "AND", "OR", "ANY",
"ALL", "SOME", "FETCH", "NEXT", "ONLY", "ASC", "DESC", "GRANT", "REVOKE", "ROLE",
"USER", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP",
}
# 动态获取子查询 # 动态获取子查询
if original_table in ctrSqlDict: if original_table in ctrSqlDict and alias_name not in sql_keywords:
# 使用 ctrSqlDict 中的子查询替换表名 # 使用 ctrSqlDict 中的子查询替换表名
replaced = f"{keyword} ({ctrSqlDict[original_table]}) {alias_part}" replaced = f"{keyword} ({ctrSqlDict[original_table]}) {alias_part}"
else: else:
# 默认处理逻辑:判断 alias 是否为关键字 # 默认处理逻辑:判断 alias 是否为关键字
sql_keywords = {
"SELECT", "INSERT", "UPDATE", "DELETE", "MERGE", "TRUNCATE",
"VALUES", "RETURNING", "FROM", "WHERE", "GROUP", "HAVING", "ORDER",
"LIMIT", "OFFSET", "DISTINCT", "ALL", "UNION", "INTERSECT", "EXCEPT",
"JOIN", "INNER", "LEFT", "RIGHT", "FULL", "CROSS", "NATURAL", "USING", "ON",
"TABLE", "VIEW", "INDEX", "PRIMARY", "KEY", "FOREIGN", "REFERENCES", "NOT",
"NULL", "UNIQUE", "CHECK", "DEFAULT", "IF", "ELSE", "CASE", "WHEN", "THEN",
"END", "LOOP", "FOR", "WHILE", "CREATE", "ALTER", "DROP", "TRUNCATE", "COMMENT",
"EXISTS", "IN", "IS", "LIKE", "ILIKE", "SIMILAR", "BETWEEN", "AND", "OR", "ANY",
"ALL", "SOME", "FETCH", "NEXT", "ONLY", "ASC", "DESC", "GRANT", "REVOKE", "ROLE",
"USER", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP",
}
if alias_name and alias_name.upper().split()[0] not in sql_keywords: if alias_name and alias_name.upper().split()[0] not in sql_keywords:
replaced = f"{keyword} ({subquery}) {alias_part}" replaced = f"{keyword} ({subquery}) {alias_part}"
@ -835,3 +769,93 @@ def generate_pagination_sql(page_object: MetaSecurityApiModel, db_type: str) ->
raise ValueError(f"不支持的数据库类型: {db_type}") raise ValueError(f"不支持的数据库类型: {db_type}")
return newStrSql return newStrSql
def _extract_identifiers(token):
"""
Identifier IdentifierList 中抽取 (schema, table)
返回格式为 'schema.table'如果有 schema否则 None
"""
if isinstance(token, Identifier):
real_name = token.get_real_name() # table
parent_name = token.get_parent_name() # schema if exists
if real_name and parent_name:
return f"{parent_name}.{real_name}"
# 处理像 schema.table AS alias 这种形式
# token.get_name() 返回 alias 或 table,根据需要可扩展
return None
async def get_tables_from_sql(sql_query: str):
"""
使用 sqlparse 解析 SQL 并返回 schema.table 列表去重
支持嵌套子查询函数别名JOININTOUPDATE
只返回包含 schema 的标识符即有点号的
"""
parsed = sqlparse.parse(sql_query)
tables = set()
for stmt in parsed:
# 遍历语句的 token 树,寻找顶层的 FROM/JOIN/INTO/UPDATE 子句
for token in stmt.tokens:
# 忽略函数、子查询整体(它们会在自己的 stmt 中被处理)
# 但我们需要遍历整个树以捕获顶层的 Identifier/IdentifierList
if token.is_group:
# 递归遍历 group 内的 token
for t in token.flatten():
# 跳过在函数内部的 FROM(例如 EXTRACT(... FROM ...))
# 方法:判断最近的父级 group 是否为 Function(我们用了 flatten,故这里检查 parent types is hard)
# 简化办法:如果 token 的上层类型是 Function 的一部分,skip(handled by checking surrounding tokens)
pass
# 更好的做法:直接按 sqlparse 提供的机制遍历并查找 Identifier/IdentifierList
for token in stmt.tokens:
if token.ttype is DML and token.normalized.upper() in ("UPDATE",):
# UPDATE table_name ...
# 下一个非空白 token 往往是 Identifier
nxt = stmt.token_next(stmt.token_index(token), skip_ws=True, skip_cm=True)
if nxt:
name = _extract_identifiers(nxt[1]) if isinstance(nxt[1], (Identifier, IdentifierList)) else None
if name:
tables.add(name)
# 使用遍历获取所有 Identifier / IdentifierList 出现在 FROM 或 JOIN 后面的情况
# 这里遍历 token 序列并在遇到 FROM/JOIN/INTO/UPDATE 时提取后续 identifier
idx = 0
tokens = list(stmt.tokens)
while idx < len(tokens):
t = tokens[idx]
if t.is_whitespace:
idx += 1
continue
if t.ttype is Keyword and t.normalized.upper() in ("FROM", "JOIN", "INTO"):
# 找下一个有意义的 token(可能是 Identifier 或 IdentifierList 或 Parenthesis 表示子查询)
nxt = stmt.token_next(idx, skip_ws=True, skip_cm=True)
if nxt:
tok = nxt[1]
# 如果是 parenthesis -> 子查询,跳过
if tok.is_group and isinstance(tok, Function):
# 函数内的 FROM(如 EXTRACT(...))会被解析为 Function 的一部分 —— 跳过
pass
else:
# 处理 Identifier 或 IdentifierList
if isinstance(tok, Identifier):
name = _extract_identifiers(tok)
if name:
tables.add(name)
elif isinstance(tok, IdentifierList):
for ident in tok.get_identifiers():
name = _extract_identifiers(ident)
if name:
tables.add(name)
else:
# 可能是直接的 Name token 'schema.table'(未被识别为 Identifier)
txt = tok.value
if "." in txt:
parts = txt.strip().strip('`"\'').split(".")
if len(parts) == 2:
tables.add(f"{parts[0]}.{parts[1]}")
idx += 1
continue
idx += 1
if not tables:
raise ValueError("SQL 解析失败,未找到任何 schema.table 结构")
return sorted(tables)

201
vue-fastapi-frontend/src/views/dataAsset/assetDetail/index.vue

@ -132,103 +132,112 @@
<!-- --> <!-- -->
<el-dialog title="编辑资产" v-model="open" width="600px" append-to-body> <el-dialog title="编辑资产" v-model="open" width="600px" append-to-body>
<el-form :model="form" :rules="rules" ref="assetRef" label-width="120px"> <el-form :model="form" :rules="rules" ref="assetRef" label-width="120px">
<el-form-item label="资产编号" prop="astNo"> <el-form-item label="资产编号" prop="astNo">
<el-input v-model="form.astNo" placeholder="请输入" :disabled="true" /> <el-input v-model="form.astNo" placeholder="请输入" :disabled="true" />
</el-form-item> </el-form-item>
<el-form-item label="表英文名称" prop="dataAstEngName"> <el-form-item label="表英文名称" prop="dataAstEngName">
<el-input v-model="form.dataAstEngName" placeholder="请输入" :disabled="true" /> <el-input v-model="form.dataAstEngName" placeholder="请输入" :disabled="true" />
</el-form-item> </el-form-item>
<el-form-item label="表中文名称" prop="dataAstCnName"> <el-form-item label="表中文名称" prop="dataAstCnName">
<el-input v-model="form.dataAstCnName" placeholder="请输入" :disabled="true" /> <el-input v-model="form.dataAstCnName" placeholder="请输入" :disabled="true" />
</el-form-item> </el-form-item>
<el-form-item label="表类型" prop="dataAstType"> <el-form-item label="表类型" prop="dataAstType">
<el-select v-model="form.dataAstType" placeholder="请选择" clearable style="width: 100%" :disabled="true"> <el-select v-model="form.dataAstType" placeholder="请选择" clearable style="width: 100%" :disabled="true">
<el-option label="表" value="表" />
<el-option label="表" value="表" /> <el-option label="报表" value="报表" />
<el-option label="报表" value="报表" /> </el-select>
</el-select> </el-form-item>
</el-form-item> <el-form-item label="资产应用场景" prop="dataAstScreen">
<el-form-item label="资产应用场景" prop="dataAstScreen"> <el-select v-model="form.dataAstScreen" placeholder="请选择" clearable style="width: 100%">
<el-select v-model="form.dataAstScreen" placeholder="请选择" clearable style="width: 100%"> <el-option label="智能助手" value="智能助手" />
<el-option label="智能助手" value="智能助手" /> <el-option label="API" value="API" />
<el-option label="API" value="API" /> </el-select>
</el-select> </el-form-item>
</el-form-item> <el-form-item label="应用场景分类" prop="dataAstScrenClas">
<el-form-item label="应用场景分类" prop="dataAstScrenClas"> <el-select v-model="form.dataAstScrenClas" placeholder="请选择" clearable style="width: 100%">
<el-select v-model="form.dataAstScrenClas" placeholder="请选择" clearable style="width: 100%"> <el-option v-for="(item, index) in dataAstScrenClas_list" :key="index" :label="item" :value="item" />
<el-option v-for="(item, index) in dataAstScrenClas_list" :key="index" :label="item" :value="item" /> </el-select>
</el-select> </el-form-item>
</el-form-item>
<!-- 修改为文本域 -->
<el-form-item label="资产描述" prop="dataAstDesc"> <el-form-item label="资产描述" prop="dataAstDesc">
<el-input v-model="form.dataAstDesc" placeholder="请输入" /> <el-input type="textarea" v-model="form.dataAstDesc" placeholder="请输入" />
</el-form-item> </el-form-item>
<el-form-item label="资产内容" prop="dataAstCont">
<el-input v-model="form.dataAstCont" placeholder="请输入" /> <!-- 修改为文本域 -->
</el-form-item> <el-form-item label="资产内容" prop="dataAstCont">
<el-form-item label="资产常见问题" prop="dataAstFaq"> <el-input type="textarea" v-model="form.dataAstCont" placeholder="请输入" />
<el-input v-model="form.dataAstFaq" placeholder="请输入" /> </el-form-item>
</el-form-item>
<el-form-item label="数据资产来源" prop="dataAstSrc"> <!-- 修改为文本域 -->
<el-tree-select v-model="form.dataAstSrc" :data="treeDataChildren" <el-form-item label="资产常见问题" prop="dataAstFaq">
:props="{ value: 'name', label: 'name', children: 'children' }" value-key="id" placeholder="请选择" <el-input type="textarea" v-model="form.dataAstFaq" placeholder="请输入" />
check-strictly /> </el-form-item>
</el-form-item>
<el-form-item label="选择标签:"> <el-form-item label="数据资产来源" prop="dataAstSrc">
<el-select <el-tree-select v-model="form.dataAstSrc" :data="treeDataChildren"
v-model="currentAstTag.clasOnum" :props="{ value: 'name', label: 'name', children: 'children' }" value-key="id" placeholder="请选择"
filterable check-strictly />
style="width: 240px" </el-form-item>
@change="changeAstTag"
> <el-form-item label="选择标签:">
<el-option v-for="item in metaClasList" :key="item.clasOnum" :value="item.clasOnum" :label="item.clasOnum+' - '+item.clasName"/> <el-select
</el-select> v-model="currentAstTag.clasOnum"
</el-form-item> filterable
<el-form-item> style="width: 240px"
<el-button type="primary" icon="Plus" @click="addAstTag">新增</el-button> @change="changeAstTag"
</el-form-item> >
</el-form> <el-option v-for="item in metaClasList" :key="item.clasOnum" :value="item.clasOnum" :label="item.clasOnum+' - '+item.clasName"/>
</el-select>
<el-table v-loading="loading" :data="astTags"> </el-form-item>
<el-table-column label="标签编号" width="80" align="center" prop="onum"></el-table-column> <el-form-item>
<el-table-column label="标签名称" width="120" align="center" prop="clasName"></el-table-column> <el-button type="primary" icon="Plus" @click="addAstTag">新增</el-button>
<el-table-column label="标签值" width="170" align="center" prop="clasValue" > </el-form-item>
<template #default="scope"> </el-form>
<el-input @input="changeTagValue(scope.row)" v-model="scope.row.clasValue" :disabled="scope.row.clasEffFlag !== '1'"></el-input>
</template> <el-table v-loading="loading" :data="astTags">
</el-table-column> <el-table-column label="标签编号" width="80" align="center" prop="onum"></el-table-column>
<el-table-column label="标签值说明" width="170" align="center" prop="tagRemark"> <el-table-column label="标签名称" width="120" align="center" prop="clasName"></el-table-column>
<template #default="scope"> <el-table-column label="标签值" width="170" align="center" prop="clasValue">
<el-input @input="changeTagValue(scope.row)" v-model="scope.row.tagRemark" :disabled="scope.row.clasEffFlag !== '1'"></el-input> <template #default="scope">
</template> <el-input @input="changeTagValue(scope.row)" v-model="scope.row.clasValue" :disabled="scope.row.clasEffFlag !== '1'"></el-input>
</el-table-column>
<el-table-column label="标签状态" align="center" prop="clasEffFlag">
<template #default="scope">
<span v-if="scope.row.clasEffFlag === '1'" style="color:#67C23A;">{{'有效'}}</span>
<span v-else style="color: #F56C6C">{{'已删除'}}</span>
</template>
</el-table-column>
<el-table-column label="设置方式" width="80" align="center" prop="tagSource">
<template #default="scope">
<span>{{scope.row.tagSource ? scope.row.tagSource:'自动'}}</span>
</template>
</el-table-column>
<el-table-column label="设置对象" width="80" align="center" prop="setUser"></el-table-column>
<el-table-column label="设置时间" width="150" align="center" prop="setTime"></el-table-column>
<el-table-column label="操作" align="center" width="80">
<template #default="scope">
<el-button v-if="scope.row.clasEffFlag === '1'" link type="danger" icon="Delete" @click.prevent="deleteTag(scope.row)">删除</el-button>
<el-button v-if="scope.row.clasEffFlag === '0'" link type="success" icon="RefreshLeft" @click.prevent="revertTag(scope.row)">恢复</el-button>
</template>
</el-table-column>
</el-table> <template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template> </template>
</el-dialog> </el-table-column>
<el-table-column label="标签值说明" width="170" align="center" prop="tagRemark">
<template #default="scope">
<el-input @input="changeTagValue(scope.row)" v-model="scope.row.tagRemark" :disabled="scope.row.clasEffFlag !== '1'"></el-input>
</template>
</el-table-column>
<el-table-column label="标签状态" align="center" prop="clasEffFlag">
<template #default="scope">
<span v-if="scope.row.clasEffFlag === '1'" style="color:#67C23A;">{{'有效'}}</span>
<span v-else style="color: #F56C6C">{{'已删除'}}</span>
</template>
</el-table-column>
<el-table-column label="设置方式" width="80" align="center" prop="tagSource">
<template #default="scope">
<span>{{scope.row.tagSource ? scope.row.tagSource:'自动'}}</span>
</template>
</el-table-column>
<el-table-column label="设置对象" width="80" align="center" prop="setUser"></el-table-column>
<el-table-column label="设置时间" width="150" align="center" prop="setTime"></el-table-column>
<el-table-column label="操作" align="center" width="80">
<template #default="scope">
<el-button v-if="scope.row.clasEffFlag === '1'" link type="danger" icon="Delete" @click.prevent="deleteTag(scope.row)">删除</el-button>
<el-button v-if="scope.row.clasEffFlag === '0'" link type="success" icon="RefreshLeft" @click.prevent="revertTag(scope.row)">恢复</el-button>
</template>
</el-table-column>
</el-table>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div> </div>
</template> </template>

7
vue-fastapi-frontend/src/views/dataAsset/directory/components/FormDialog.vue

@ -55,7 +55,7 @@
<template #default="{ data }"> <template #default="{ data }">
<div class="custom-tree-node"> <div class="custom-tree-node">
<span>{{ <span>{{
data.dataAssetCatalogName || data.dataAssetSysName data.dataAssetCatalogName || getNameById(data.dataAssetSysName)
}}</span> }}</span>
</div> </div>
</template> </template>
@ -84,6 +84,8 @@
<script setup> <script setup>
import { computed, nextTick } from 'vue' import { computed, nextTick } from 'vue'
import { getNameById, getIdByName } from '@/utils/dsSysUtils';
import { import {
getDirectory, getDirectory,
addDirectory, addDirectory,
@ -179,7 +181,8 @@ const filterAssetTree = (tree) => {
if (node.children) { if (node.children) {
node.children = filterAssetTree(node.children) // node.children = filterAssetTree(node.children) //
} }
return node.rel_status !== 1 || hasAsset(node.dataAssetCatalogAstno) // return node.rel_status !== 1 || hasAsset(node.dataAssetCatalogAstno)
return true
}) })
} }

5
vue-fastapi-frontend/src/views/meta/metatask/index.vue

@ -506,10 +506,13 @@
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
<div style="color: #909399; font-size: 13px; margin-bottom: 4px;margin-left: 20px;">
</div>
<el-form-item label="模式列表" prop="dbSName"> <el-form-item label="模式列表" prop="dbSName">
<el-input <el-input
v-model="form.dbSName" v-model="form.dbSName"
placeholder="请输入模式列表" placeholder="请输入模式列表,不填即采集全部的模式"
maxlength="30" maxlength="30"
:disabled="isEdit" :disabled="isEdit"
style="width: 80%" style="width: 80%"

49
vue-fastapi-frontend/src/views/metadataConfig/bizPermiConfig/index.vue

@ -52,6 +52,7 @@
stripe stripe
> >
<el-table-column type="selection" width="55" /> <el-table-column type="selection" width="55" />
<el-table-column prop="onum" label="主键" />
<el-table-column prop="bizName" label="业务域" /> <el-table-column prop="bizName" label="业务域" />
<el-table-column prop="objType" label="对象类型"> <el-table-column prop="objType" label="对象类型">
<template #default="{ row }"> <template #default="{ row }">
@ -133,7 +134,39 @@
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="对象名称" prop="objValue">
<el-select
v-model="form.objValue"
placeholder="请选择"
maxlength="30"
@change="handleObjValueChange"
>
<el-option
v-for="dict in userOrRoleList"
:key="dict.id"
:label="dict.name"
:value="dict.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="安全等级" prop="secLevelSummary">
<el-select
v-model="form.secLevelSummary"
placeholder="请选择安全等级"
maxlength="30"
>
<el-option
v-for="dict in secList"
:key="dict.onum"
:label="dict.secLevelSummary"
:value="dict.secLevelSummary"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="是否停用" prop="isStop"> <el-form-item label="是否停用" prop="isStop">
<el-select v-model="form.isStop" placeholder="请选择状态"> <el-select v-model="form.isStop" placeholder="请选择状态">
<el-option label="运行" :value=true /> <el-option label="运行" :value=true />
@ -158,6 +191,7 @@ import {
addBizPermiConfig, addBizPermiConfig,
updateBizPermiConfig, updateBizPermiConfig,
listBizConfigAll, listBizConfigAll,
listMetadataSec,
delBizPermiConfig delBizPermiConfig
} from '@/api/metadataConfig/metadataConfig' } from '@/api/metadataConfig/metadataConfig'
import { listUser} from "@/api/system/user"; import { listUser} from "@/api/system/user";
@ -168,6 +202,7 @@ const queryForm = reactive({
pageNum: 1, pageNum: 1,
pageSize: 10 pageSize: 10
}) })
const secList = ref([])
const permList = ref([]) const permList = ref([])
const total = ref(0) const total = ref(0)
@ -204,6 +239,7 @@ const form = reactive({
objType: '', objType: '',
objName: '', objName: '',
objValue: '', objValue: '',
secLevelSummary:'',
isStop: null isStop: null
}) })
function changeMetaSecurityObj(data){ function changeMetaSecurityObj(data){
@ -312,6 +348,7 @@ if (title.value.includes('新增')) {
bizOnumList: form.bizOnum, bizOnumList: form.bizOnum,
objType: form.objType, objType: form.objType,
objName: form.objName, objName: form.objName,
secLevelSummary: form.secLevelSummary,
objValue: form.objValue, // objValue: form.objValue, //
isStop: form.isStop, isStop: form.isStop,
} }
@ -322,6 +359,7 @@ if (title.value.includes('新增')) {
onum: form.onum, onum: form.onum,
bizOnum: form.bizOnum, bizOnum: form.bizOnum,
objType: form.objType, objType: form.objType,
secLevelSummary: form.secLevelSummary,
objName: form.objName, objName: form.objName,
objValue: form.objValue, // objValue: form.objValue, //
isStop: form.isStop, isStop: form.isStop,
@ -369,7 +407,14 @@ function deleteSelected() {
}) })
.catch(() => {}) .catch(() => {})
} }
async function getSecList() {
try {
const res = await listMetadataSec({pageSize:100,pageNum:1})
secList.value = res.rows
} catch (error) {
ElMessage.error('获取安全等级列表失败,请重试')
}
}
function handleClose(done) { function handleClose(done) {
permFormRef.value.resetFields() permFormRef.value.resetFields()
done() done()
@ -379,6 +424,8 @@ onMounted(() => {
getList() getList()
getRoleOrUserList(); getRoleOrUserList();
getBizList(); getBizList();
getSecList()
}) })
</script> </script>

Loading…
Cancel
Save