diff --git a/vue-fastapi-backend/module_admin/controller/metatask_controller.py b/vue-fastapi-backend/module_admin/controller/metatask_controller.py index 93357e3..63ef56e 100644 --- a/vue-fastapi-backend/module_admin/controller/metatask_controller.py +++ b/vue-fastapi-backend/module_admin/controller/metatask_controller.py @@ -47,14 +47,16 @@ async def get_process_instances_list( return ResponseUtil.success(model_content=config_page_query_result) # 获取工作流实例节点 @metataskController.get( - '/task_nodes/{id}', dependencies=[Depends(CheckUserInterfaceAuth('meta:metatask:log'))] + '/task_nodes/{id}/{projectType}', dependencies=[Depends(CheckUserInterfaceAuth('meta:metatask:log'))] ) async def get_task_nodes_list( request: Request, - id:int,current_user: CurrentUserModel = Depends(LoginService.get_current_user) + id:int, + projectType:str, + current_user: CurrentUserModel = Depends(LoginService.get_current_user) ): - config_page_query_result = await MetataskService.get_task_nodes_services(request, id,current_user) + config_page_query_result = await MetataskService.get_task_nodes_services(request, id,projectType,current_user) logger.info('获取成功') return ResponseUtil.success(rows=config_page_query_result) @@ -136,7 +138,6 @@ async def up_or_down_meta_metatask( query_db: AsyncSession = Depends(get_db), current_user: CurrentUserModel = Depends(LoginService.get_current_user), ): - edit_config_result = await MetataskService.up_or_down_metatask_services(request, query_db,current_user, DownOrUpdate.id,DownOrUpdate.type) logger.info(edit_config_result.message) diff --git a/vue-fastapi-backend/module_admin/entity/vo/dataSource_vo.py b/vue-fastapi-backend/module_admin/entity/vo/dataSource_vo.py index c676f7c..2e67e51 100644 --- a/vue-fastapi-backend/module_admin/entity/vo/dataSource_vo.py +++ b/vue-fastapi-backend/module_admin/entity/vo/dataSource_vo.py @@ -69,6 +69,7 @@ class ProcessDefinition(BaseModel): expectedParallelismNumber: Optional[int] = Field(None, description="Expected parallelism number") dryRun: Optional[int] = Field(None, description="Dry run flag") scheduleTime: Optional[str] = Field(None, description="Schedule time") + projectType: Optional[str] = Field(default='meta', description="Schedule time") # class Schedule(BaseModel): # startTime: Optional[datetime] = Field(default=None, description='更新时间') @@ -88,6 +89,7 @@ class ParmScheduleVo(BaseModel): warningGroupId: Optional[int] = Field(None, description="Warning group ID") metaTaskId: Optional[int] = Field(None, description="metaTaskId") workerGroup: Optional[str] = Field(None, description="Worker group") + projectType: Optional[str] = Field(default='meta', description="Worker group") environmentCode: Optional[int] = Field(None, description="Environment code") processDefinitionCode: Optional[int] = Field(None, description="Process definition code") crontab: Optional[str] = Field(default=None, description='更新时间') @@ -97,6 +99,7 @@ class ParmScheduleVo(BaseModel): class ProcessInstancePage(BaseModel): searchVal: Optional[str] = Field(default=None, description="Name of the task node") + projectType: Optional[str] = Field(default='meta', description="Worker group") page_num: int = Field(default=1, description='当前页码') page_size: int = Field(default=10, description='每页记录数') diff --git a/vue-fastapi-backend/module_admin/entity/vo/metatask_vo.py b/vue-fastapi-backend/module_admin/entity/vo/metatask_vo.py index d5de986..c9ab0af 100644 --- a/vue-fastapi-backend/module_admin/entity/vo/metatask_vo.py +++ b/vue-fastapi-backend/module_admin/entity/vo/metatask_vo.py @@ -80,6 +80,7 @@ class DeleteMetataskModel(BaseModel): """ metatask_ids: str ds_ids: str + class OperaMetataskModel(BaseModel): """ @@ -87,7 +88,7 @@ class OperaMetataskModel(BaseModel): """ id: str type:str - + class CrudMetataskResponse(BaseModel): """ 操作参数配置响应模型 diff --git a/vue-fastapi-backend/module_admin/service/metasecurity_service.py b/vue-fastapi-backend/module_admin/service/metasecurity_service.py index ce2c741..f4eaf75 100644 --- a/vue-fastapi-backend/module_admin/service/metasecurity_service.py +++ b/vue-fastapi-backend/module_admin/service/metasecurity_service.py @@ -517,149 +517,228 @@ async def get_table_configs(query_db, page_object, user, role_id_list, table_nam "user_row_list": user_row_list, "isHave":isHave } -async def generate_sql(tablesRowCol:dict, table_columns:dict): - sql_queries = {} +# async def generate_sql(tablesRowCol:dict, table_columns:dict): +# sql_queries = {} - # 1. 列控制 - # 遍历每个表 - no_configTable_name="" - for table_name, table_configs in tablesRowCol.items(): - if not table_configs.get("isHave", False): - no_configTable_name += table_name + "," - if no_configTable_name: - no_configTable_name = no_configTable_name.rstrip(',') - raise ValueError(f"表:{no_configTable_name}均未配置行列数据安全") +# # 1. 列控制 +# # 遍历每个表 +# no_configTable_name="" +# for table_name, table_configs in tablesRowCol.items(): +# if not table_configs.get("isHave", False): +# no_configTable_name += table_name + "," +# if no_configTable_name: +# no_configTable_name = no_configTable_name.rstrip(',') +# raise ValueError(f"表:{no_configTable_name}均未配置行列数据安全") +# for table_name, config in tablesRowCol.items(): +# # 获取该表的字段名 +# columns = {col.lower(): col for col in table_columns[table_name]} # 将字段名转为小写 +# # 初始化 SELECT 部分:用字典存储字段名,值是 null 字段名 +# select_columns = {col: f"null as {col}" for col in columns} + +# # 处理角色列配置 +# for col in config["role_col_list"]: +# # If dbCName is "ALL", handle it as a special case +# if col.dbCName == "ALL": +# if col.ctrl_type == '0': # If ctrl_type is '0', prefix all columns with null +# for db_column in columns: # Assuming 'user' is the table name +# select_columns[db_column] = f"null as {db_column}" # 仍然保留 null 前缀 +# elif col.ctrl_type == '1': # If ctrl_type is '1', use actual column names +# for db_column in columns: +# select_columns[db_column] = db_column # 使用实际字段名 +# else: +# # Handle specific columns listed in dbCName +# db_columns = [db_column.strip().lower() for db_column in col.dbCName.split(",")] +# for db_column in db_columns: +# db_column = db_column.strip() +# if db_column in columns: # Check if the column exists in the table +# if col.ctrl_type == '0': # If ctrl_type is '0', prefix with null +# select_columns[db_column] = f"null as {db_column}" # 仍然保留 null 前缀 +# elif col.ctrl_type == '1': # If ctrl_type is '1', use actual column name +# select_columns[db_column] = db_column # 使用实际字段名 +# # 处理用户列配置 +# for col in config["user_col_list"]: +# if col.dbCName == "ALL": # 如果 dbCName 为 "ALL" +# if col.ctrl_type == "0": # ctrlType 为 0,字符串字段 +# for db_column in columns: # 对所有字段加上 null +# select_columns[db_column] = f"null as {db_column}" # 仍然保留 null 前缀 +# elif col.ctrl_type == "1": # ctrlType 为 1,实际数据库字段 +# for db_column in columns: # 使用实际字段名,不加 null +# select_columns[db_column] = db_column # 使用实际字段名 +# else: # 处理 dbCName 不为 "ALL" 的情况 +# db_columns = [db_column.strip().lower() for db_column in col.dbCName.split(",")] +# for db_column in db_columns: +# db_column = db_column.strip() +# if db_column in columns: +# if col.ctrl_type == "0": +# select_columns[db_column] = f"null as {db_column}" # 仍然保留 null 前缀 +# elif col.ctrl_type == "1": +# select_columns[db_column] = db_column # 使用实际字段名 +# # 生成 SQL 查询 +# sql_queries[table_name] = f"SELECT {', '.join(select_columns.values())} FROM {table_name}" +# # 2.行控制 +# select_rows={} +# # 处理角色行配置 +# for row in config["role_row_list"]: +# # 仅仅对固定值有效,不加行限制 +# if row.ctrl_value == "ALL" and row.ctrl_type == '0': +# # 控制方式 --固定值 +# select_rows[row.dbCName] = "" +# else: +# if row.ctrl_type == '0': +# # row.ctrl_value 是逗号分隔的字符串时,改为 IN 语句 +# if "," in row.ctrl_value: +# # 将 ctrl_value 按逗号分割,并用单引号包裹每个值 +# values = [f"'{value.strip()}'" for value in row.ctrl_value.split(",")] +# select_rows[row.dbCName] = f"{row.dbCName} IN ({', '.join(values)})" +# else: +# select_rows[row.dbCName] = f"{row.dbCName} = '{row.ctrl_value}'" +# if row.ctrl_type == '1': +# tab_col_value=row.ctrl_value.split(".") +# if len(tab_col_value) != 2: +# raise RuntimeError(f"{row.dbCName}字段控制类型为表字段,未维护正确的值") +# select_rows[row.dbCName] = f"{row.dbCName} in (select {tab_col_value[1]} from {row.dbSName}.{tab_col_value[0]} where user_id = '1')" +# # 处理用户行配置 +# for row in config["user_row_list"]: +# # 仅仅对固定值有效,不加行限制 +# if row.ctrl_value == "ALL" and row.ctrl_type == '0': +# # 控制方式 --固定值 +# select_rows[row.dbCName] = "" +# else: +# if row.ctrl_type == '0': +# # row.obj_value 是逗号分隔的字符串时,改为 IN 语句 +# if "," in row.ctrl_value: +# # 将 obj_value 按逗号分割,并用单引号包裹每个值 +# values = [f"'{value.strip()}'" for value in row.ctrl_value.split(",")] +# select_rows[row.dbCName] = f"{row.dbCName} IN ({', '.join(values)})" +# else: +# select_rows[row.dbCName] = f"{row.dbCName} = '{row.ctrl_value}'" +# if row.ctrl_type == '1': +# tab_col_value=row.ctrl_value.split(".") +# if len(tab_col_value) != 2: +# raise RuntimeError(f"{row.dbCName}字段控制类型为表字段,未维护正确的值") +# select_rows[row.dbCName] = f"{row.dbCName} in (select {tab_col_value[1]} from {row.dbSName}.{tab_col_value[0]} where user_id = '1')" +# if select_rows.values(): +# where_conditions = " AND ".join(select_rows.values()) +# if where_conditions: +# sql_queries[table_name] += " WHERE " + where_conditions +# else: +# sql_queries[table_name] += " WHERE 1 = 0" +# return sql_queries +async def generate_sql(tablesRowCol: dict, table_columns: dict): + sql_queries = {} + + # ========= 0. 校验是否存在未配置安全策略的表 ========= + no_config_tables = [ + table_name + for table_name, cfg in tablesRowCol.items() + if not cfg.get("isHave", False) + ] + if no_config_tables: + raise ValueError(f"表:{','.join(no_config_tables)} 均未配置行列数据安全") + + # ========= 1. 遍历每个表 ========= for table_name, config in tablesRowCol.items(): - # 获取该表的字段名 - columns = {col.lower(): col for col in table_columns[table_name]} # 将字段名转为小写 - # 初始化 SELECT 部分:用字典存储字段名,值是 null 字段名 - select_columns = {col: f"null as {col}" for col in columns} - - # 处理角色列配置 - for col in config["role_col_list"]: - # If dbCName is "ALL", handle it as a special case - if col.dbCName == "ALL": - if col.ctrl_type == '0': # If ctrl_type is '0', prefix all columns with null - for db_column in columns: # Assuming 'user' is the table name - select_columns[db_column] = f"null as {db_column}" # 仍然保留 null 前缀 - elif col.ctrl_type == '1': # If ctrl_type is '1', use actual column names - for db_column in columns: - select_columns[db_column] = db_column # 使用实际字段名 - else: - # Handle specific columns listed in dbCName - db_columns = [db_column.strip().lower() for db_column in col.dbCName.split(",")] - for db_column in db_columns: - db_column = db_column.strip() - if db_column in columns: # Check if the column exists in the table - if col.ctrl_type == '0': # If ctrl_type is '0', prefix with null - select_columns[db_column] = f"null as {db_column}" # 仍然保留 null 前缀 - elif col.ctrl_type == '1': # If ctrl_type is '1', use actual column name - select_columns[db_column] = db_column # 使用实际字段名 - # 处理用户列配置 - for col in config["user_col_list"]: - if col.dbCName == "ALL": # 如果 dbCName 为 "ALL" - if col.ctrl_type == "0": # ctrlType 为 0,字符串字段 - for db_column in columns: # 对所有字段加上 null - select_columns[db_column] = f"null as {db_column}" # 仍然保留 null 前缀 - elif col.ctrl_type == "1": # ctrlType 为 1,实际数据库字段 - for db_column in columns: # 使用实际字段名,不加 null - select_columns[db_column] = db_column # 使用实际字段名 - else: # 处理 dbCName 不为 "ALL" 的情况 - db_columns = [db_column.strip().lower() for db_column in col.dbCName.split(",")] - for db_column in db_columns: - db_column = db_column.strip() - if db_column in columns: - if col.ctrl_type == "0": - select_columns[db_column] = f"null as {db_column}" # 仍然保留 null 前缀 - elif col.ctrl_type == "1": - select_columns[db_column] = db_column # 使用实际字段名 - # 生成 SQL 查询 - sql_queries[table_name] = f"SELECT {', '.join(select_columns.values())} FROM {table_name}" - # 2.行控制 - select_rows={} - # 处理角色行配置 - for row in config["role_row_list"]: - # 仅仅对固定值有效,不加行限制 - if row.ctrl_value == "ALL" and row.ctrl_type == '0': - # 控制方式 --固定值 - select_rows[row.dbCName] = "" - else: - if row.ctrl_type == '0': - # row.ctrl_value 是逗号分隔的字符串时,改为 IN 语句 - if "," in row.ctrl_value: - # 将 ctrl_value 按逗号分割,并用单引号包裹每个值 - values = [f"'{value.strip()}'" for value in row.ctrl_value.split(",")] - select_rows[row.dbCName] = f"{row.dbCName} IN ({', '.join(values)})" - else: - select_rows[row.dbCName] = f"{row.dbCName} = '{row.ctrl_value}'" - if row.ctrl_type == '1': - tab_col_value=row.ctrl_value.split(".") - if len(tab_col_value) != 2: - raise RuntimeError(f"{row.dbCName}字段控制类型为表字段,未维护正确的值") - select_rows[row.dbCName] = f"{row.dbCName} in (select {tab_col_value[1]} from {row.dbSName}.{tab_col_value[0]} where user_id = '1')" - # 处理用户行配置 - for row in config["user_row_list"]: - # 仅仅对固定值有效,不加行限制 - if row.ctrl_value == "ALL" and row.ctrl_type == '0': - # 控制方式 --固定值 - select_rows[row.dbCName] = "" + # 字段映射:小写 → 原始字段名 + columns = {col.lower(): col for col in table_columns[table_name]} + + # ==================================================== + # 2. 列控制(不可见优先) + # ==================================================== + + # 0 = 不可见,1 = 可见,None = 未配置(默认不可见) + column_visibility = {col: None for col in columns} + + def set_visibility(col_name: str, ctrl_type: str): + """ + 不可见(ctrl_type=0) 优先级最高 + """ + if ctrl_type == '0': + column_visibility[col_name] = '0' + elif ctrl_type == '1': + if column_visibility[col_name] != '0': + column_visibility[col_name] = '1' + + def handle_col_config(col_cfg_list): + for col in col_cfg_list: + if col.dbCName == "ALL": + for db_col in columns: + set_visibility(db_col, col.ctrl_type) + else: + db_cols = [c.strip().lower() for c in col.dbCName.split(",")] + for db_col in db_cols: + if db_col in columns: + set_visibility(db_col, col.ctrl_type) + + # 角色列 + 用户列 + handle_col_config(config.get("role_col_list", [])) + handle_col_config(config.get("user_col_list", [])) + + # 生成 SELECT 字段 + select_columns = [] + for col in columns: + if column_visibility[col] == '1': + select_columns.append(col) else: - if row.ctrl_type == '0': - # row.obj_value 是逗号分隔的字符串时,改为 IN 语句 - if "," in row.ctrl_value: - # 将 obj_value 按逗号分割,并用单引号包裹每个值 - values = [f"'{value.strip()}'" for value in row.ctrl_value.split(",")] - select_rows[row.dbCName] = f"{row.dbCName} IN ({', '.join(values)})" - else: - select_rows[row.dbCName] = f"{row.dbCName} = '{row.ctrl_value}'" - if row.ctrl_type == '1': - tab_col_value=row.ctrl_value.split(".") - if len(tab_col_value) != 2: - raise RuntimeError(f"{row.dbCName}字段控制类型为表字段,未维护正确的值") - select_rows[row.dbCName] = f"{row.dbCName} in (select {tab_col_value[1]} from {row.dbSName}.{tab_col_value[0]} where user_id = '1')" - if select_rows.values(): - where_conditions = " AND ".join(select_rows.values()) - if where_conditions: - sql_queries[table_name] += " WHERE " + where_conditions + select_columns.append(f"null as {col}") + + sql = f"SELECT {', '.join(select_columns)} FROM {table_name}" + + # ==================================================== + # 3. 行控制 + # ==================================================== + + where_conditions = [] + + def build_row_condition(row): + # 固定值 & ALL → 不加限制 + if row.ctrl_type == '0' and row.ctrl_value == "ALL": + return None + + # 固定值 + if row.ctrl_type == '0': + if "," in row.ctrl_value: + values = [f"'{v.strip()}'" for v in row.ctrl_value.split(",")] + return f"{row.dbCName} IN ({', '.join(values)})" + return f"{row.dbCName} = '{row.ctrl_value}'" + + # 表字段 + if row.ctrl_type == '1': + tab_col = row.ctrl_value.split(".") + if len(tab_col) != 2: + raise RuntimeError( + f"{row.dbCName} 字段控制类型为表字段,但未维护正确的值" + ) + table, column = tab_col + return ( + f"{row.dbCName} IN (" + f"SELECT {column} FROM {row.dbSName}.{table} " + f"WHERE user_id = '1')" + ) + return None + + def handle_row_config(row_cfg_list): + for row in row_cfg_list: + condition = build_row_condition(row) + if condition: + where_conditions.append(condition) + + # 角色行 + 用户行 + handle_row_config(config.get("role_row_list", [])) + handle_row_config(config.get("user_row_list", [])) + + # ==================================================== + # 4. WHERE 拼接(无行权限则拒绝访问) + # ==================================================== + + if where_conditions: + sql += " WHERE " + " AND ".join(where_conditions) else: - sql_queries[table_name] += " WHERE 1 = 0" + sql += " WHERE 1 = 0" + + sql_queries[table_name] = sql + return sql_queries -# async def replace_table_with_subquery(ctrSqlDict, oldStrSql): -# table_alias_map = {} # 存储表名和别名的映射 -# for table_name, subquery in ctrSqlDict.items(): -# # 构建正则表达式,匹配表名及可能的别名 -# pattern = ( -# r'(\b(?:[a-zA-Z_][a-zA-Z0-9_]*\.)?' # 匹配模式名(可选) -# + re.escape(table_name) # 转义表名 -# + r'\b)' # 结束表名 -# r'(\s+(?:AS\s+)?(\w+))?' # 捕获别名部分(含 AS 或直接别名) -# r'(?=\s*[\w\(\)]*)' # 确保后面是合法 SQL 语法,不是 SQL 关键字 -# ) -# def replace(match): -# original_table = match.group(1) # 原始表名(可能含模式名) -# alias_part = match.group(2) # 别名部分(含空格、AS 或直接别名) -# alias_name = match.group(3) # 别名名称(无 AS 前缀) -# if original_table not in table_alias_map: -# # 处理表名后直接跟着 SQL 关键字的情况 -# sql_keywords = {"LIMIT", "WHERE", "ORDER", "GROUP", "HAVING", "JOIN", "ON", "USING", "UNION", -# "EXCEPT", "INTERSECT", "FETCH", "OFFSET"} -# if alias_name and alias_name.upper().split()[0] not in sql_keywords: -# # 已存在别名,且别名后没有紧跟 SQL 关键字,保留原别名 -# replaced = f"({subquery}) {alias_part}" -# table_alias_map[original_table] = alias_part -# else: -# # 无别名时,或者别名无效(如 LIMIT),添加默认别名 -# alias = original_table.split('.')[-1] -# replaced = f"({subquery}) AS {alias}{alias_part}" -# table_alias_map[original_table] = alias -# else: -# alias = table_alias_map[original_table] -# replaced = f"{alias}" # 使用别名 -# return replaced -# # 执行替换(忽略大小写) -# oldStrSql = re.sub(pattern, replace, oldStrSql, flags=re.IGNORECASE) - -# return oldStrSql + diff --git a/vue-fastapi-backend/module_admin/service/metatask_service.py b/vue-fastapi-backend/module_admin/service/metatask_service.py index d4dfe6b..561e9c7 100644 --- a/vue-fastapi-backend/module_admin/service/metatask_service.py +++ b/vue-fastapi-backend/module_admin/service/metatask_service.py @@ -1228,8 +1228,16 @@ class MetataskService: process.runMode='RUN_MODE_SERIAL' process.processInstancePriority='MEDIUM' process.dryRun=0 - process.scheduleTime="{complementStartDate:'2025-01-12 00:00:00',complementEndDate:'2025-01-12 00:00:00'}" + today = datetime.now().strftime("%Y-%m-%d") + process.scheduleTime = ( + "{" + f"complementStartDate:'{today} 00:00:00'," + f"complementEndDate:'{today} 00:00:00'" + "}" + ) projectCode = await request.app.state.redis.get(f'{RedisInitKeyConfig.SYS_CONFIG.key}:sys.ds.projectcode') + if(process.projectType=='dispatch'): + projectCode = await request.app.state.redis.get(f'{RedisInitKeyConfig.SYS_CONFIG.key}:sys.ds.taskBatchCode') url=f'{AppConfig.ds_server_url}/dolphinscheduler/projects/'+projectCode+'/executors/start-process-instance' headers = {'dashUserName': current_user.user.user_name, 'dashPassword': current_user.user.password, 'Content-Type': 'application/x-www-form-urlencoded'} # form_data = {key: str(value) for key, value in process.__dict__.items()} @@ -1433,6 +1441,8 @@ class MetataskService: cls, request: Request, query_object: ProcessInstancePage,current_user: CurrentUserModel ): projectCode = await request.app.state.redis.get(f'{RedisInitKeyConfig.SYS_CONFIG.key}:sys.ds.projectcode') + if(query_object.projectType=='dispatch'): + projectCode = await request.app.state.redis.get(f'{RedisInitKeyConfig.SYS_CONFIG.key}:sys.ds.taskBatchCode') url = f'{AppConfig.ds_server_url}/dolphinscheduler/projects/{projectCode}/process-instances?pageNo={query_object.page_num}&pageSize={query_object.page_size}&searchVal={query_object.searchVal}' headers = {'dashUserName': current_user.user.user_name, 'dashPassword': current_user.user.password} response = requests.get(url, headers=headers, verify=False) @@ -1452,9 +1462,11 @@ class MetataskService: @classmethod async def get_task_nodes_services( -cls, request: Request,id:int,current_user: CurrentUserModel +cls, request: Request,id:int, projectType:str,current_user: CurrentUserModel ): projectCode = await request.app.state.redis.get(f'{RedisInitKeyConfig.SYS_CONFIG.key}:sys.ds.projectcode') + if(projectType=='dispatch'): + projectCode = await request.app.state.redis.get(f'{RedisInitKeyConfig.SYS_CONFIG.key}:sys.ds.taskBatchCode') url = f'{AppConfig.ds_server_url}/dolphinscheduler/projects/{projectCode}/process-instances/{id}/tasks' headers = {'dashUserName': current_user.user.user_name, 'dashPassword': current_user.user.password} response = requests.get(url, headers=headers, verify=False) diff --git a/vue-fastapi-frontend/src/api/meta/metatask.js b/vue-fastapi-frontend/src/api/meta/metatask.js index 945f9c8..752079c 100644 --- a/vue-fastapi-frontend/src/api/meta/metatask.js +++ b/vue-fastapi-frontend/src/api/meta/metatask.js @@ -18,9 +18,9 @@ export function listInstances(query) { }) } // 查询节点 -export function taskNodes(id) { +export function taskNodes(id,projectType) { return request({ - url: '/default-api/meta/metatask/task_nodes/'+id, + url: '/default-api/meta/metatask/task_nodes/'+id+'/'+projectType, method: 'get', }) } @@ -72,10 +72,11 @@ export function updatemetatask(data) { }) } // 上下线 -export function downOrUpmetatask(id,type) { +export function downOrUpmetatask(id,type,projectType) { const data = { id, - type + type, + projectType } return request({ url: '/default-api/meta/metatask/upOrdown', diff --git a/vue-fastapi-frontend/src/api/metadataConfig/metadataConfig.js b/vue-fastapi-frontend/src/api/metadataConfig/metadataConfig.js index b552067..008d0f4 100644 --- a/vue-fastapi-frontend/src/api/metadataConfig/metadataConfig.js +++ b/vue-fastapi-frontend/src/api/metadataConfig/metadataConfig.js @@ -441,7 +441,7 @@ export function dsmetataskdelete(data) { // 查询任务定义列表 export function listTaskDefinitions(query) { return request({ - url: '/ds-api/dolphinscheduler/projects/15094505099232/task-definition', + url: '/ds-api/dolphinscheduler/projects/15094505099232/process-definition', method: 'get', params: { pageSize: query.pageSize || 10, diff --git a/vue-fastapi-frontend/src/utils/dsSysUtils.js b/vue-fastapi-frontend/src/utils/dsSysUtils.js index f1ad9a1..4f78ea1 100644 --- a/vue-fastapi-frontend/src/utils/dsSysUtils.js +++ b/vue-fastapi-frontend/src/utils/dsSysUtils.js @@ -4,12 +4,12 @@ export function getNameById(id) { const userStore = useUserStore(); const list = userStore.dsSysList || []; const item = list.find(x => x.id == id); - return item ? item.name : ''; + return item ? item.name : id; } export function getIdByName(name) { const userStore = useUserStore(); const list = userStore.dsSysList || []; const item = list.find(x => x.name == name); - return item ? item.id : null; + return item ? item.id : name; } diff --git a/vue-fastapi-frontend/src/views/dataAsset/assetDetail/index.vue b/vue-fastapi-frontend/src/views/dataAsset/assetDetail/index.vue index 4231e69..dd3f8b5 100644 --- a/vue-fastapi-frontend/src/views/dataAsset/assetDetail/index.vue +++ b/vue-fastapi-frontend/src/views/dataAsset/assetDetail/index.vue @@ -254,6 +254,8 @@ const defaultProps = { import useUserStore from '@/store/modules/user'; // 注意路径是否正确 +import { get } from "@vueuse/core/index.cjs"; +import { getNameById, getIdByName } from '@/utils/dsSysUtils'; const metaClasList = ref([]); const userStore = useUserStore(); // 正确调用 @@ -322,7 +324,7 @@ function getDeptTree() { /** 节点单击事件 */ function handleNodeClick(data) { - queryParams.value.dataAstSrc = data.name; + queryParams.value.dataAstSrc = getIdByName(data.name); handleQuery(); }; diff --git a/vue-fastapi-frontend/src/views/datastd/stdcode/index.vue b/vue-fastapi-frontend/src/views/datastd/stdcode/index.vue index a120713..4a39469 100644 --- a/vue-fastapi-frontend/src/views/datastd/stdcode/index.vue +++ b/vue-fastapi-frontend/src/views/datastd/stdcode/index.vue @@ -376,6 +376,7 @@ const resetQuery = () => { cdType: '', sysName: '', srcSys: '', + classId:'code', pageNum: 1, pageSize: 10 }; diff --git a/vue-fastapi-frontend/src/views/meta/metatask/dsDialog.vue b/vue-fastapi-frontend/src/views/meta/metatask/dsDialog.vue index 463dd6d..f666d71 100644 --- a/vue-fastapi-frontend/src/views/meta/metatask/dsDialog.vue +++ b/vue-fastapi-frontend/src/views/meta/metatask/dsDialog.vue @@ -117,7 +117,7 @@ import { dsmetatask,dsmetataskdetail } from "@/api/meta/metatask"; import { dsmetataskSec} from "@/api/metadataConfig/metadataConfig"; import { dsmetataskBiz } from "@/api/taskMetadataConfig/metadataConfig"; import Crontab from '@/components/Crontab' -import { ElMessage } from 'element-plus' +import { ElMessage,ElMessageBox } from 'element-plus' export default { components: { Crontab }, @@ -131,6 +131,7 @@ export default { type: Function, required: true, }, + projectType: String, }, setup(props) { @@ -212,7 +213,8 @@ const taskSubmitMap = { }; const handleds = () => { - const submitData = addDateRange(form, dateRange.value); + const submitData = addDateRange(form, dateRange.value,props.projectType); + submitData.projectType=props.projectType; const submitApi = taskSubmitMap[props.processDefinitionType]; if (!submitApi) { @@ -220,13 +222,33 @@ const handleds = () => { return; } - submitApi(submitData).then((response) => { - if (response.success) { - visible.value = false; - ElMessage.success(response.msg); - props.getList(); + const doSubmit = () => { + submitApi(submitData).then((response) => { + if (response.success) { + visible.value = false; + ElMessage.success(response.msg); + props.getList(); + } + }); + }; + + // ⚠️ 一律提示风险,确认后才提交 + ElMessageBox.confirm( + '请确认调度频率配置合理。若设置为秒级或过高频率,' + + '可能导致 DS 调度服务压力过大甚至崩溃,是否继续执行?', + '调度风险提示', + { + type: 'warning', + confirmButtonText: '确认执行', + cancelButtonText: '取消' } - }); + ) + .then(() => { + doSubmit(); + }) + .catch(() => { + // 用户取消,不做任何处理 + }); }; // Helper function to add the date range to the form diff --git a/vue-fastapi-frontend/src/views/meta/metatask/index.vue b/vue-fastapi-frontend/src/views/meta/metatask/index.vue index 504e554..6da4b2a 100644 --- a/vue-fastapi-frontend/src/views/meta/metatask/index.vue +++ b/vue-fastapi-frontend/src/views/meta/metatask/index.vue @@ -538,6 +538,7 @@ :environmentList="environmentList" :workerGroupList="workerGroupList" :processDefinitionCode="dsIds" + projectType="meta" /> diff --git a/vue-fastapi-frontend/src/views/meta/metatask/logsDialog.vue b/vue-fastapi-frontend/src/views/meta/metatask/logsDialog.vue index a393909..34a9e97 100644 --- a/vue-fastapi-frontend/src/views/meta/metatask/logsDialog.vue +++ b/vue-fastapi-frontend/src/views/meta/metatask/logsDialog.vue @@ -102,6 +102,7 @@ const { meta_instance_status } = proxy.useDict("meta_instance_status"); // Props const props = defineProps({ defindName: String, + prpjectType: String, }); // State @@ -128,6 +129,7 @@ const fetchInstances = (name) => { page_num: currentPage.value, page_size: pageSize.value, searchVal: name, + projectType: props.prpjectType, }).then((response) => { instances.value = response.rows; total.value = response.total; @@ -150,7 +152,7 @@ const handlePageChange = (page) => { // 选中实例,加载任务节点 const handleFirstRowClick = (row) => { - taskNodes(row.id).then((response) => { + taskNodes(row.id,props.prpjectType).then((response) => { taskNodesData.value = response.rows; if (taskNodesData.value.length > 0) { diff --git a/vue-fastapi-frontend/src/views/meta/metatask/runDialog.vue b/vue-fastapi-frontend/src/views/meta/metatask/runDialog.vue index 6fd0748..08f3fb3 100644 --- a/vue-fastapi-frontend/src/views/meta/metatask/runDialog.vue +++ b/vue-fastapi-frontend/src/views/meta/metatask/runDialog.vue @@ -67,7 +67,7 @@ import { runmetatask } from "@/api/meta/metatask"; import { ElMessage } from 'element-plus' export default { - props: ["processDefinitionCode", "warningGroupList", "environmentList", "workerGroupList"], + props: ["processDefinitionCode", "warningGroupList", "environmentList", "workerGroupList","projectType"], data() { return { visible: false, @@ -76,6 +76,7 @@ export default { warningGroupId: undefined, environmentCode: undefined, workerGroup: undefined, + projectType: undefined, }, }; }, @@ -86,6 +87,7 @@ export default { this.visible = true; }, handleRun() { + this.form.projectType = this.projectType; runmetatask(this.form).then((response) => { if (response.success) { this.visible = false; diff --git a/vue-fastapi-frontend/src/views/meta/metatask/secConfig.vue b/vue-fastapi-frontend/src/views/meta/metatask/secConfig.vue index c3792ba..edaddb5 100644 --- a/vue-fastapi-frontend/src/views/meta/metatask/secConfig.vue +++ b/vue-fastapi-frontend/src/views/meta/metatask/secConfig.vue @@ -386,6 +386,7 @@ :environmentList="environmentList" :workerGroupList="workerGroupList" :processDefinitionCode="dsIds" + projectType="dispatch" /> diff --git a/vue-fastapi-frontend/src/views/metadataConfig/log/index.vue b/vue-fastapi-frontend/src/views/metadataConfig/log/index.vue index 1ad6aa4..38b729a 100644 --- a/vue-fastapi-frontend/src/views/metadataConfig/log/index.vue +++ b/vue-fastapi-frontend/src/views/metadataConfig/log/index.vue @@ -24,26 +24,24 @@ border stripe > - - - - - - + + + + - - - + - - + + + + + + diff --git a/vue-fastapi-frontend/src/views/metadataConfig/taskBizConfig/index.vue b/vue-fastapi-frontend/src/views/metadataConfig/taskBizConfig/index.vue index ee20b4d..e173b60 100644 --- a/vue-fastapi-frontend/src/views/metadataConfig/taskBizConfig/index.vue +++ b/vue-fastapi-frontend/src/views/metadataConfig/taskBizConfig/index.vue @@ -384,6 +384,7 @@ :environmentList="environmentList" :workerGroupList="workerGroupList" :processDefinitionCode="dsIds" + projectType="dispatch" /> - + diff --git a/vue-fastapi-frontend/src/views/system/flow/dataAssetMainAppr.vue b/vue-fastapi-frontend/src/views/system/flow/dataAssetMainAppr.vue index 5552287..a471cdc 100644 --- a/vue-fastapi-frontend/src/views/system/flow/dataAssetMainAppr.vue +++ b/vue-fastapi-frontend/src/views/system/flow/dataAssetMainAppr.vue @@ -7,7 +7,13 @@ :row-class-name="tableRowClassName" > - + + + @@ -59,7 +65,7 @@ const props = defineProps({ } }); const getSrcSysName = (id) => { - const match = dsSysList.find(item => item.id === id); + const match = dsSysList.find(item => item.id == id); return match ? match.name : id; }; // 设置行样式