diff --git a/packages/shared/lib/api/sqle/service/SqlManage/index.d.ts b/packages/shared/lib/api/sqle/service/SqlManage/index.d.ts
index 75858a868..4d539fe0c 100644
--- a/packages/shared/lib/api/sqle/service/SqlManage/index.d.ts
+++ b/packages/shared/lib/api/sqle/service/SqlManage/index.d.ts
@@ -24,6 +24,7 @@ import {
IGetGlobalSqlManageListResp,
IGetGlobalSqlManageStatisticsResp,
IGetSqlManageListResp,
+ IGetAbnormalAuditPlanInstancesResp,
IBatchUpdateSqlManageReq,
IBaseRes,
IGetSqlManageRuleTipsResp,
@@ -97,6 +98,13 @@ export interface IGetSqlManageListParams {
export interface IGetSqlManageListReturn extends IGetSqlManageListResp {}
+export interface IGetAbnormalInstanceAuditPlansV1Params {
+ project_name: string;
+}
+
+export interface IGetAbnormalInstanceAuditPlansV1Return
+ extends IGetAbnormalAuditPlanInstancesResp {}
+
export interface IBatchUpdateSqlManageParams extends IBatchUpdateSqlManageReq {
project_name: string;
}
diff --git a/packages/shared/lib/api/sqle/service/SqlManage/index.ts b/packages/shared/lib/api/sqle/service/SqlManage/index.ts
index d96a057cd..bc64fec6e 100644
--- a/packages/shared/lib/api/sqle/service/SqlManage/index.ts
+++ b/packages/shared/lib/api/sqle/service/SqlManage/index.ts
@@ -13,6 +13,8 @@ import {
IGetGlobalSqlManageStatisticsReturn,
IGetSqlManageListParams,
IGetSqlManageListReturn,
+ IGetAbnormalInstanceAuditPlansV1Params,
+ IGetAbnormalInstanceAuditPlansV1Return,
IBatchUpdateSqlManageParams,
IBatchUpdateSqlManageReturn,
IExportSqlManageV1Params,
@@ -68,6 +70,21 @@ class SqlManageService extends ServiceBase {
);
}
+ public getAbnormalInstanceAuditPlansV1(
+ params: IGetAbnormalInstanceAuditPlansV1Params,
+ options?: AxiosRequestConfig
+ ) {
+ const paramsData = this.cloneDeep(params);
+ const project_name = paramsData.project_name;
+ delete paramsData.project_name;
+
+ return this.get(
+ `/v1/projects/${project_name}/sql_manages/abnormal_audit_plan_instance`,
+ paramsData,
+ options
+ );
+ }
+
public BatchUpdateSqlManage(
params: IBatchUpdateSqlManageParams,
options?: AxiosRequestConfig
diff --git a/packages/shared/lib/api/sqle/service/common.d.ts b/packages/shared/lib/api/sqle/service/common.d.ts
index a6e1aa73b..e924fece5 100644
--- a/packages/shared/lib/api/sqle/service/common.d.ts
+++ b/packages/shared/lib/api/sqle/service/common.d.ts
@@ -4,6 +4,8 @@ import {
AuditPlanParamResV1TypeEnum,
AuditPlanReportResV1AuditLevelEnum,
AuditPlanSQLHeadV1TypeEnum,
+ AuditPlanTypeResBaseActiveStatusEnum,
+ AuditPlanTypeResBaseLastCollectionStatusEnum,
AuditPlanTypesV1InstanceTypeEnum,
AuditResDataV1AuditLevelEnum,
AuditTaskResV1AuditLevelEnum,
@@ -32,6 +34,7 @@ import {
HighPriorityConditionReqOperatorEnum,
HighPriorityConditionResV1TypeEnum,
InstanceAuditPlanInfoActiveStatusEnum,
+ InstanceAuditPlanInfoLastCollectionStatusEnum,
InstanceAuditPlanResV1ActiveStatusEnum,
InstanceTipResV1SupportedBackupStrategyEnum,
ModuleRedDotModuleNameEnum,
@@ -122,6 +125,12 @@ export interface IRuleCategoryStatistic {
tag?: string;
}
+export interface IAbnormalAuditPlanInstance {
+ instance_audit_plan_id?: number;
+
+ instance_name?: string;
+}
+
export interface IAffectRows {
count?: number;
@@ -301,10 +310,14 @@ export interface IAuditPlanSQLResV1 {
}
export interface IAuditPlanTypeResBase {
+ active_status?: AuditPlanTypeResBaseActiveStatusEnum;
+
audit_plan_id?: number;
desc?: string;
+ last_collection_status?: AuditPlanTypeResBaseLastCollectionStatusEnum;
+
token?: string;
type?: string;
@@ -1072,6 +1085,14 @@ export interface IGenModifylSQLReqV1 {
database_schema_objects?: IDatabaseSchemaObject[];
}
+export interface IGetAbnormalAuditPlanInstancesResp {
+ code?: number;
+
+ data?: IAbnormalAuditPlanInstance[];
+
+ message?: string;
+}
+
export interface IGetAuditPlanAnalysisDataResV1 {
code?: number;
@@ -2119,6 +2140,8 @@ export interface IInstanceAuditPlanInfo {
id?: number;
+ last_collection_status?: InstanceAuditPlanInfoLastCollectionStatusEnum;
+
last_collection_time?: string;
total_sql_nums?: number;
@@ -3994,6 +4017,8 @@ export interface IExecResultCount {
export interface IFullSyncAuditPlanSQLsReqV2 {
audit_plan_sql_list?: IAuditPlanSQLReqV2[];
+
+ error_message?: string;
}
export interface IGetAuditFileExecStatisticRes {
@@ -4182,6 +4207,8 @@ export interface IUpdateWorkflowScheduleReqV2 {
export interface IUploadInstanceAuditPlanSQLsReqV2 {
audit_plan_sql_list?: IAuditPlanSQLReqV2[];
+
+ error_message?: string;
}
export interface IWorkflowRecordResV2 {
diff --git a/packages/shared/lib/api/sqle/service/common.enum.ts b/packages/shared/lib/api/sqle/service/common.enum.ts
index 0534ef9f6..7951af768 100644
--- a/packages/shared/lib/api/sqle/service/common.enum.ts
+++ b/packages/shared/lib/api/sqle/service/common.enum.ts
@@ -50,6 +50,18 @@ export enum AuditPlanSQLHeadV1TypeEnum {
'sql' = 'sql'
}
+export enum AuditPlanTypeResBaseActiveStatusEnum {
+ 'normal' = 'normal',
+
+ 'disabled' = 'disabled'
+}
+
+export enum AuditPlanTypeResBaseLastCollectionStatusEnum {
+ 'normal' = 'normal',
+
+ 'abnormal' = 'abnormal'
+}
+
export enum AuditPlanTypesV1InstanceTypeEnum {
'MySQL' = 'MySQL',
@@ -332,6 +344,12 @@ export enum InstanceAuditPlanInfoActiveStatusEnum {
'disabled' = 'disabled'
}
+export enum InstanceAuditPlanInfoLastCollectionStatusEnum {
+ 'normal' = 'normal',
+
+ 'abnormal' = 'abnormal'
+}
+
export enum InstanceAuditPlanResV1ActiveStatusEnum {
'normal' = 'normal',
diff --git a/packages/sqle/src/locale/zh-CN/managementConf.ts b/packages/sqle/src/locale/zh-CN/managementConf.ts
index bd6cdb184..23cbeef9f 100644
--- a/packages/sqle/src/locale/zh-CN/managementConf.ts
+++ b/packages/sqle/src/locale/zh-CN/managementConf.ts
@@ -34,7 +34,8 @@ export default {
scanStatus: '采集状态',
notificationMethod: '推送方式',
createdAt: '创建时间',
- creator: '创建人'
+ creator: '创建人',
+ abnormalTips: 'SQL采集存在异常'
},
action: {
disabled: {
@@ -117,7 +118,14 @@ export default {
connectionInfo: '连接信息',
collectedSqlCount: '采集到的SQL数',
problematicSqlCount: '审核有问题的SQL数',
- lastCollectionTime: '最近一次采集时间'
+ lastCollectionTime: '最近一次采集时间',
+ taskStatus: {
+ disabled: '停用',
+ normal: '运行中',
+ abnormal: '运行异常'
+ },
+ abnormalTips:
+ '请根据"execute extract sql failed"关键字到sqled.log日志中检索相关信息'
},
actions: {
enabled: '启用',
diff --git a/packages/sqle/src/locale/zh-CN/sqlManagement.ts b/packages/sqle/src/locale/zh-CN/sqlManagement.ts
index 91f3d927e..f313d559c 100644
--- a/packages/sqle/src/locale/zh-CN/sqlManagement.ts
+++ b/packages/sqle/src/locale/zh-CN/sqlManagement.ts
@@ -13,6 +13,8 @@ export default {
problemSQlNum: '问题SQL数',
optimizedSQLNum: '已优化SQL数'
},
+ abnormalAuditPlanTips:
+ '上的SQL采集存在问题,为保障SQL管控功能正常运行,请及时进行诊断排查',
ceTips:
'SQL管控为用户提供SQL全生命周期监控,面板将整合所有的业务SQL,用户可以在该面板中查看项目中采集并审核的所有SQL,暴露其中的问题SQL,同时支持用户解决问题SQL。',
table: {
diff --git a/packages/sqle/src/page/SqlManagement/__snapshots__/index.test.tsx.snap b/packages/sqle/src/page/SqlManagement/__snapshots__/index.test.tsx.snap
index 26245b634..61b08c1dc 100644
--- a/packages/sqle/src/page/SqlManagement/__snapshots__/index.test.tsx.snap
+++ b/packages/sqle/src/page/SqlManagement/__snapshots__/index.test.tsx.snap
@@ -467,7 +467,7 @@ exports[`page/SqlManagement render sql management page 1`] = `
{
payload: [sqlManageListData.data[0]]
});
});
+
+ it('render abnormal status audit plan tips when request return data', async () => {
+ const request = sqlManage.getAbnormalInstanceAuditPlans();
+ request.mockImplementation(() =>
+ createSpySuccessResponse({ data: mockAbnormalInstanceAuditPlansData })
+ );
+ superRender(
);
+ expect(request).toHaveBeenCalled();
+ await act(async () => jest.advanceTimersByTime(3000));
+ expect(getBySelector('.ant-alert-warning')).toBeInTheDocument();
+ });
});
diff --git a/packages/sqle/src/page/SqlManagement/component/SQLEEIndex/index.tsx b/packages/sqle/src/page/SqlManagement/component/SQLEEIndex/index.tsx
index b7a14b389..4e5c76955 100644
--- a/packages/sqle/src/page/SqlManagement/component/SQLEEIndex/index.tsx
+++ b/packages/sqle/src/page/SqlManagement/component/SQLEEIndex/index.tsx
@@ -1,7 +1,13 @@
import { useTranslation } from 'react-i18next';
import { useBoolean, useRequest } from 'ahooks';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
-import { BasicButton, PageHeader, useTypedQuery } from '@actiontech/shared';
+import {
+ BasicButton,
+ PageHeader,
+ useTypedQuery,
+ TypedLink,
+ EmptyBox
+} from '@actiontech/shared';
import SQLStatistics, { ISQLStatisticsProps } from '../SQLStatistics';
import {
useTableFilterContainer,
@@ -11,7 +17,7 @@ import {
ColumnsSettingProps,
useTableRequestParams
} from '@actiontech/shared/lib/components/ActiontechTable';
-import SqlManage from '@actiontech/shared/lib/api/sqle/service/SqlManage';
+import { SqlManageService } from '@actiontech/shared/lib/api';
import {
IExportSqlManageV1Params,
IGetSqlManageListV2Params
@@ -42,7 +48,7 @@ import {
import { ModalName } from '../../../../data/ModalName';
import { SorterResult, TableRowSelection } from 'antd/es/table/interface';
import { ISqlManage } from '@actiontech/shared/lib/api/sqle/service/common';
-import { Spin, message } from 'antd';
+import { Spin, message, Alert, Space } from 'antd';
import SqlManagementModal from './Modal';
import EmitterKey from '../../../../data/EmitterKey';
import EventEmitter from '../../../../utils/EventEmitter';
@@ -53,7 +59,10 @@ import useGetTableFilterInfo from './hooks/useGetTableFilterInfo';
import { DownArrowLineOutlined } from '@actiontech/icons';
import useSqlManagementExceptionRedux from '../../../SqlManagementException/hooks/useSqlManagementExceptionRedux';
import useWhitelistRedux from '../../../Whitelist/hooks/useWhitelistRedux';
-import { SqlManagementTableStyleWrapper } from './style';
+import {
+ SqlManagementTableStyleWrapper,
+ AbnormalAuditPlanTipsStyleWrapper
+} from './style';
import { SqlManageAuditStatusEnum } from '@actiontech/shared/lib/api/sqle/service/common.enum';
import { GetSqlManageListV2FilterSourceEnum } from '@actiontech/shared/lib/api/sqle/service/SqlManage/index.enum';
import { ROUTE_PATHS } from '@actiontech/shared/lib/data/routePaths';
@@ -162,7 +171,9 @@ const SQLEEIndex = () => {
? GetSqlManageListV2FilterPriorityEnum.high
: undefined
};
- return handleTableRequestError(SqlManage.GetSqlManageListV2(params));
+ return handleTableRequestError(
+ SqlManageService.GetSqlManageListV2(params)
+ );
},
{
refreshDeps: [
@@ -198,6 +209,17 @@ const SQLEEIndex = () => {
}
);
+ const { data: abnormalInstances, loading: getAbnormalInstancesLoading } =
+ useRequest(() =>
+ SqlManageService.getAbnormalInstanceAuditPlansV1({
+ project_name: projectName
+ }).then((res) => {
+ if (res.data.code === ResponseCode.SUCCESS) {
+ return res.data.data;
+ }
+ })
+ );
+
const openModal = useCallback((name: ModalName, row?: ISqlManage) => {
if (row) {
setSelectData(row);
@@ -279,7 +301,7 @@ const SQLEEIndex = () => {
return;
}
updateRemarkProtect.current = true;
- SqlManage.BatchUpdateSqlManage({
+ SqlManageService.BatchUpdateSqlManage({
project_name: projectName,
sql_manage_id_list: [id],
remark
@@ -368,7 +390,7 @@ const SQLEEIndex = () => {
DB_TYPE_RULE_NAME_SEPARATOR
)?.[1]
} as IExportSqlManageV1Params;
- SqlManage.exportSqlManageV1(params, { responseType: 'blob' })
+ SqlManageService.exportSqlManageV1(params, { responseType: 'blob' })
.then((res) => {
if (res.data.code === ResponseCode.SUCCESS) {
messageApi.success(
@@ -445,7 +467,7 @@ const SQLEEIndex = () => {
}, []);
return (
-
+
{messageContextHolder}
{
errorMessage={getListError}
loading={loading}
/>
+
+
+
+
+ {abnormalInstances?.map((instance, index) => {
+ return (
+
+ {instance.instance_name}
+
+ );
+ })}
+
+ {t('sqlManagement.abnormalAuditPlanTips')}
+ >
+ }
+ type="warning"
+ showIcon
+ />
+
+
{/* table */}
{
filterCustomProps={filterCustomProps}
/>
`
.ant-table-body {
- max-height: calc(100vh - 338px) !important;
+ max-height: ${(hasAbnormalAuditPlan) =>
+ `calc(100vh - ${hasAbnormalAuditPlan ? '388px' : '338px'}) !important`};
}
.audit-status .ant-tag {
width: fit-content;
}
`;
+
+export const AbnormalAuditPlanTipsStyleWrapper = styled('div')`
+ padding: 10px 40px 0;
+`;
diff --git a/packages/sqle/src/page/SqlManagementConf/Common/ConfForm/DataSourceSelection/index.tsx b/packages/sqle/src/page/SqlManagementConf/Common/ConfForm/DataSourceSelection/index.tsx
index b95c184b7..db68116c2 100644
--- a/packages/sqle/src/page/SqlManagementConf/Common/ConfForm/DataSourceSelection/index.tsx
+++ b/packages/sqle/src/page/SqlManagementConf/Common/ConfForm/DataSourceSelection/index.tsx
@@ -11,7 +11,7 @@ import {
} from '@actiontech/shared/lib/global';
import { Form } from 'antd';
import useInstance from '../../../../../hooks/useInstance';
-import { useContext, useEffect, useMemo, useCallback } from 'react';
+import { useContext, useEffect, useMemo } from 'react';
import useDatabaseType from '../../../../../hooks/useDatabaseType';
import { ConfFormContext } from '../context';
import { SqlManagementConfFormFields } from '../index.type';
@@ -103,8 +103,8 @@ const DataSourceSelection: React.FC = () => {
updateDriverNameList();
}, [updateDriverNameList]);
- const updateInstanceListByProjectName = useCallback(
- (id: string) => {
+ useEffect(() => {
+ if (!!instanceIdByUrlSearchParams && !!businessByUrlSearchParams) {
updateInstanceList(
{
project_name: projectName,
@@ -113,34 +113,32 @@ const DataSourceSelection: React.FC = () => {
},
{
onSuccess: (list) => {
- const instance = list.find((v) => v.instance_id === id);
+ const instance = list.find(
+ (v) => v.instance_id === instanceIdByUrlSearchParams
+ );
form.setFieldsValue({
+ businessScope: businessByUrlSearchParams,
+ instanceId: instanceIdByUrlSearchParams,
instanceName: instance?.instance_name ?? '',
instanceType: instance?.instance_type ?? ''
});
}
}
);
- },
- [form, projectName, updateInstanceList]
- );
-
- useEffect(() => {
- if (!!instanceIdByUrlSearchParams && !!businessByUrlSearchParams) {
- form.setFieldsValue({
- businessScope: businessByUrlSearchParams,
- instanceId: instanceIdByUrlSearchParams
- });
- updateInstanceListByProjectName(instanceIdByUrlSearchParams);
} else if (!!defaultValue) {
- updateInstanceListByProjectName(defaultValue.instanceId as string);
+ updateInstanceList({
+ project_name: projectName,
+ functional_module:
+ getInstanceTipListV1FunctionalModuleEnum.create_audit_plan
+ });
}
}, [
businessByUrlSearchParams,
instanceIdByUrlSearchParams,
defaultValue,
- updateInstanceListByProjectName,
- form
+ updateInstanceList,
+ form,
+ projectName
]);
useEffect(() => {
diff --git a/packages/sqle/src/page/SqlManagementConf/Detail/Overview/__tests__/__snapshots__/index.test.tsx.snap b/packages/sqle/src/page/SqlManagementConf/Detail/Overview/__tests__/__snapshots__/index.test.tsx.snap
index 8a4a71092..35f5f081b 100644
--- a/packages/sqle/src/page/SqlManagementConf/Detail/Overview/__tests__/__snapshots__/index.test.tsx.snap
+++ b/packages/sqle/src/page/SqlManagementConf/Detail/Overview/__tests__/__snapshots__/index.test.tsx.snap
@@ -1,5 +1,500 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
+exports[`test Overview render abnormal status audit plan 1`] = `
+
+`;
+
exports[`test Overview should match snapshot when hasOpPermission is equal false 1`] = `
{
return {
@@ -175,4 +177,27 @@ describe('test Overview', () => {
const { container } = customRender();
expect(container).toMatchSnapshot();
});
+
+ it('render abnormal status audit plan', async () => {
+ getInstanceAuditPlanOverviewSpy.mockImplementation(() =>
+ createSpySuccessResponse({
+ data: [
+ {
+ ...mockInstanceAuditPlanInfo[0],
+ active_status: InstanceAuditPlanInfoActiveStatusEnum.normal,
+ last_collection_status:
+ InstanceAuditPlanInfoLastCollectionStatusEnum.abnormal
+ },
+ {
+ ...mockInstanceAuditPlanInfo[1],
+ active_status: undefined
+ }
+ ]
+ })
+ );
+ const { container } = customRender();
+ await act(async () => jest.advanceTimersByTime(3000));
+ expect(container).toMatchSnapshot();
+ expect(screen.getByText('运行异常')).toBeInTheDocument();
+ });
});
diff --git a/packages/sqle/src/page/SqlManagementConf/Detail/Overview/column.tsx b/packages/sqle/src/page/SqlManagementConf/Detail/Overview/column.tsx
index b59e85e78..7e93325bb 100644
--- a/packages/sqle/src/page/SqlManagementConf/Detail/Overview/column.tsx
+++ b/packages/sqle/src/page/SqlManagementConf/Detail/Overview/column.tsx
@@ -2,13 +2,17 @@ import { ActiontechTableColumn } from '@actiontech/shared/lib/components/Actiont
import { t } from '../../../../locale';
import { formatTime } from '@actiontech/shared/lib/utils/Common';
import { IInstanceAuditPlanInfo } from '@actiontech/shared/lib/api/sqle/service/common';
-import { SensitiveDisplay, TypedLink } from '@actiontech/shared';
-import { InstanceAuditPlanInfoActiveStatusEnum } from '@actiontech/shared/lib/api/sqle/service/common.enum';
+import { SensitiveDisplay, TypedLink, BasicToolTip } from '@actiontech/shared';
+import {
+ InstanceAuditPlanInfoLastCollectionStatusEnum,
+ InstanceAuditPlanInfoActiveStatusEnum
+} from '@actiontech/shared/lib/api/sqle/service/common.enum';
import { TableColumnWithIconStyleWrapper } from '@actiontech/shared/lib/styleWrapper/element';
import {
CheckCircleOutlined,
CloseHexagonOutlined,
- InfoHexagonOutlined
+ InfoHexagonOutlined,
+ InfoCircleOutlined
} from '@actiontech/icons';
import { Typography } from 'antd';
import { ROUTE_PATHS } from '@actiontech/shared/lib/data/routePaths';
@@ -62,13 +66,30 @@ export const ConfDetailOverviewColumns: (
{
dataIndex: 'active_status',
title: () => t('managementConf.detail.overview.column.status'),
- render: (status) => {
+ render: (status, record) => {
if (status === InstanceAuditPlanInfoActiveStatusEnum.disabled) {
return (
- {t('managementConf.list.table.column.taskStatus.disabled')}
+ {t('managementConf.detail.overview.column.taskStatus.disabled')}
+
+
+ );
+ }
+ if (
+ status === InstanceAuditPlanInfoActiveStatusEnum.normal &&
+ record.last_collection_status ===
+ InstanceAuditPlanInfoLastCollectionStatusEnum.abnormal
+ ) {
+ return (
+
+ }
+ title={t('managementConf.detail.overview.column.abnormalTips')}
+ />
+
+ {t('managementConf.detail.overview.column.taskStatus.abnormal')}
);
@@ -78,7 +99,7 @@ export const ConfDetailOverviewColumns: (
- {t('managementConf.list.table.column.taskStatus.normal')}
+ {t('managementConf.detail.overview.column.taskStatus.normal')}
);
diff --git a/packages/sqle/src/page/SqlManagementConf/Detail/__tests__/__snapshots__/index.test.tsx.snap b/packages/sqle/src/page/SqlManagementConf/Detail/__tests__/__snapshots__/index.test.tsx.snap
index 29080a8e1..7a5275369 100644
--- a/packages/sqle/src/page/SqlManagementConf/Detail/__tests__/__snapshots__/index.test.tsx.snap
+++ b/packages/sqle/src/page/SqlManagementConf/Detail/__tests__/__snapshots__/index.test.tsx.snap
@@ -759,7 +759,7 @@ exports[`test SqlManagementConf/Detail/index.tsx should match snapshot 2`] = `
/>
- 启用
+ 运行中
@@ -1060,7 +1060,7 @@ exports[`test SqlManagementConf/Detail/index.tsx should match snapshot 2`] = `
/>
- 启用
+ 运行中
@@ -1178,7 +1178,7 @@ exports[`test SqlManagementConf/Detail/index.tsx should match snapshot 2`] = `
/>
- 启用
+ 运行中
diff --git a/packages/sqle/src/page/SqlManagementConf/List/__tests__/__snapshots__/index.test.tsx.snap b/packages/sqle/src/page/SqlManagementConf/List/__tests__/__snapshots__/index.test.tsx.snap
index 203e5b050..56df12818 100644
--- a/packages/sqle/src/page/SqlManagementConf/List/__tests__/__snapshots__/index.test.tsx.snap
+++ b/packages/sqle/src/page/SqlManagementConf/List/__tests__/__snapshots__/index.test.tsx.snap
@@ -575,11 +575,23 @@ exports[`test sqle/SqlManagementConf/List render close task type filter field 1`
-
- 静态扫描
-
+
+
+
|
-
- test instance name
-
+
+
+
|
-
- 静态扫描
-
+
+
+
|
-
- 静态扫描
-
+
+
+
|
-
- test instance name
-
+
+
+
|
-
- 静态扫描
-
+
+
+
|
|
+
+
+
+
+
+
+
+
+
+
+ 全部数据源
+
+
+
+
+
+
+
+
+ 全部任务类型
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+