mirror of
https://github.com/didi/KnowStreaming.git
synced 2026-01-07 23:28:24 +08:00
kafka-manager 2.0
This commit is contained in:
32
kafka-manager-console/src/lib/api-cache.ts
Normal file
32
kafka-manager-console/src/lib/api-cache.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
class ApiCache {
|
||||
public apiCacheMap = new Map();
|
||||
|
||||
public setCacheMap = (key: string, data: any, timeout: number = 1 * 60 * 60 * 1000) => {
|
||||
this.apiCacheMap.set(key, {
|
||||
data,
|
||||
timeout,
|
||||
startTime: (new Date()).getTime(),
|
||||
});
|
||||
}
|
||||
|
||||
public getDataFromCache = (key: string) => {
|
||||
const cacheData = this.apiCacheMap.get(key);
|
||||
|
||||
if (!cacheData) return null;
|
||||
|
||||
const { data, timeout, startTime } = cacheData;
|
||||
const currentTime = (new Date()).getTime();
|
||||
|
||||
if ((currentTime - startTime) > timeout) {
|
||||
this.deleteDataFromCache(key);
|
||||
return null;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
public deleteDataFromCache = (key: string) => {
|
||||
return this.apiCacheMap.delete(key);
|
||||
}
|
||||
}
|
||||
|
||||
export const apiCache = new ApiCache();
|
||||
884
kafka-manager-console/src/lib/api.ts
Normal file
884
kafka-manager-console/src/lib/api.ts
Normal file
@@ -0,0 +1,884 @@
|
||||
import fetch , { formFetch } from './fetch';
|
||||
import { IUploadFile, IUser, IQuotaModelItem, ILimitsItem, ITopic, IOrderParams, ISample, IMigration, IExecute, IEepand, IUtils, ITopicMetriceParams, IRegister, IEditTopic, IExpand, IDeleteTopic, INewRegions, INewLogical, IRebalance, INewBulidEnums, ITrigger, IApprovalOrder, IMonitorSilences, IConfigure, IBatchApproval } from 'types/base-type';
|
||||
import { IRequestParams } from 'types/alarm';
|
||||
import { apiCache } from 'lib/api-cache';
|
||||
|
||||
export const getRegionIdcs = () => {
|
||||
return fetch(`/normal/configs/idcs`);
|
||||
};
|
||||
|
||||
export const getAccount = () => {
|
||||
return fetch(`/normal/accounts/account`);
|
||||
};
|
||||
|
||||
/**
|
||||
* topic 相关接口
|
||||
* @see http://127.0.0.1:8080/swagger-ui.html#/
|
||||
*/
|
||||
|
||||
export const getMytopics = () => {
|
||||
return fetch(`/normal/topics/mine`);
|
||||
};
|
||||
|
||||
export const getExpiredTopics = () => {
|
||||
return fetch(`/normal/topics/expired`);
|
||||
};
|
||||
|
||||
export const getBaseInfo = () => {
|
||||
return fetch(`/normal/topics/my-topics`);
|
||||
};
|
||||
|
||||
export const getAllTopic = () => {
|
||||
return fetch(`/normal/topics`);
|
||||
};
|
||||
|
||||
export const getAuthorities = (appId: string, clusterId: number, topicName: string) => {
|
||||
return fetch(`/normal/apps/${appId}/authorities?clusterId=${clusterId}&topicName=${topicName}`);
|
||||
};
|
||||
|
||||
export const getQuotaQuery = (appId: string, clusterId: number, topicName: string) => {
|
||||
return fetch(`/normal/apps/${appId}/quotas?clusterId=${clusterId}&topicName=${topicName}`);
|
||||
};
|
||||
|
||||
export const getTopicBroker = (clusterId: number, topicName: string) => {
|
||||
return fetch(`/${clusterId}/topics/${topicName}/brokers`);
|
||||
};
|
||||
|
||||
export const getClusters = () => {
|
||||
return fetch(`/normal/clusters/basic-info`);
|
||||
};
|
||||
|
||||
export const getAllClusters = () => {
|
||||
return fetch(`/normal/clusters/basic-info?all=true`);
|
||||
};
|
||||
|
||||
export const getApply = () => {
|
||||
return fetch(`/normal/apps?status=1`);
|
||||
};
|
||||
|
||||
// 配额
|
||||
export const updateTopic = (params: IQuotaModelItem) => {
|
||||
return fetch('/normal/topics', {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const deferTopic = (params: ILimitsItem) => {
|
||||
return fetch('/normal/topics/expired', {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
// 详情
|
||||
export const getTopicCompile = (params: ITopic) => {
|
||||
return fetch('/normal/topics', {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const getTopicSampling = (params: ISample, clusterId: number, topicName: string) => {
|
||||
return fetch(`/normal/${clusterId}/topics/${topicName}/sample`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const getTopicBasicInfo = (clusterId: number, topicName: string) => {
|
||||
return fetch(`/normal/${clusterId}/topics/${topicName}/basic-info`);
|
||||
};
|
||||
|
||||
export const getRealTimeTraffic = (clusterId: number, topicName: string) => {
|
||||
return fetch(`/normal/${clusterId}/topics/${topicName}/metrics`);
|
||||
};
|
||||
|
||||
export const getRealConsume = (clusterId: number, topicName: string) => {
|
||||
return fetch(`/normal/${clusterId}/topics/${topicName}/request-time`);
|
||||
};
|
||||
|
||||
export const getConnectionInfo = (clusterId: number, topicName: string, appId?: string) => {
|
||||
return fetch(`/normal/${clusterId}/topics/${topicName}/connections?appId=${appId}`);
|
||||
};
|
||||
|
||||
export const getConsumerGroups = (clusterId: number, topicName: string) => {
|
||||
return fetch(`/normal/${clusterId}/consumers/${topicName}/consumer-groups`);
|
||||
};
|
||||
|
||||
export const getConsumeDetails = (clusterId: number, topicName: string, consumerGroup: string, location: string) => {
|
||||
return fetch(
|
||||
`/normal/${clusterId}/consumers/${consumerGroup}/topics/${topicName}/consume-details?location=${location}`);
|
||||
};
|
||||
|
||||
export const getPartitionsInfo = (clusterId: number, topicName: string) => {
|
||||
return fetch(`/normal/${clusterId}/topics/${topicName}/partitions`);
|
||||
};
|
||||
|
||||
export const getBrokerInfo = (clusterId: number, topicName: string) => {
|
||||
return fetch(`/rd/${clusterId}/topics/${topicName}/brokers`);
|
||||
};
|
||||
|
||||
export const getAppsIdInfo = (clusterId: number, topicName: string) => {
|
||||
return fetch(`/normal/${clusterId}/topics/${topicName}/apps`);
|
||||
};
|
||||
|
||||
export const getBillInfo = (clusterId: number, topicName: string, startTime: number, endTime: number) => {
|
||||
return fetch(`/normal/${clusterId}/topics/${topicName}/bills?startTime=${startTime}&endTime=${endTime}`);
|
||||
};
|
||||
|
||||
export const resetOffset = (params: any) => {
|
||||
return fetch('/normal/consumers/offsets', {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const getTopicBusiness = (clusterId: number, topicName: string) => {
|
||||
return fetch(`/normal/${clusterId}/topics/${topicName}/business`);
|
||||
};
|
||||
|
||||
// 集群mode
|
||||
export const getClusterModes = () => {
|
||||
return fetch(`/normal/configs/cluster-modes`);
|
||||
};
|
||||
|
||||
export const getClusterComboList = () => {
|
||||
return fetch('/normal/configs/cluster-combos');
|
||||
};
|
||||
|
||||
// --------------------------
|
||||
export const getConsumeInfo = (clusterId: number) => {
|
||||
return fetch(`/${clusterId}/consumers/consumer-groups`);
|
||||
};
|
||||
|
||||
export const getConsumeGroup = (clusterId: number, consumerGroup: string, location: string) => {
|
||||
return fetch(`/${clusterId}/consumer/${consumerGroup}/topics?location=${location}`);
|
||||
};
|
||||
|
||||
// 获取echarts
|
||||
export const getTopicMetriceInfo = (parmas: ITopicMetriceParams) => {
|
||||
const { clusterId, topicName, startTime, endTime, appId } = parmas;
|
||||
// tslint:disable-next-line:max-line-length
|
||||
return fetch(`/normal/${clusterId}/topics/${topicName}/metrics-history?startTime=${startTime}&endTime=${endTime}&appId=${appId}`);
|
||||
};
|
||||
|
||||
export const getTopicMetriceTake = (params: ITopicMetriceParams) => {
|
||||
const { clusterId, topicName, startTime, endTime } = params;
|
||||
// tslint:disable-next-line:max-line-length
|
||||
return fetch(`/normal/${clusterId}/topics/${topicName}/request-time-history?startTime=${startTime}&endTime=${endTime}`);
|
||||
};
|
||||
/**
|
||||
* mycluster
|
||||
*/
|
||||
|
||||
export const getClusterBasicInfo = (clusterId: number) => {
|
||||
return fetch(`/normal/clusters/${clusterId}/basic-info`);
|
||||
};
|
||||
|
||||
export const getClusterDetailRealTime = (clusterId: number) => {
|
||||
return fetch(`/normal/clusters/${clusterId}/metrics`);
|
||||
};
|
||||
|
||||
export const getClusterDetailMetrice = (clusterId: number, startTime: string, endTime: string) => {
|
||||
return fetch(`/normal/clusters/${clusterId}/metrics-history?startTime=${startTime}&endTime=${endTime}`);
|
||||
};
|
||||
|
||||
export const getClusterDetailTopics = (clusterId: number) => {
|
||||
return fetch(`/normal/clusters/${clusterId}/topics`);
|
||||
};
|
||||
|
||||
export const getClusterMetaTopics = (clusterId: number) => {
|
||||
return fetch(`/normal/clusters/${clusterId}/topic-metadata`);
|
||||
};
|
||||
|
||||
export const getClusterDetailBroker = (clusterId: number) => {
|
||||
return fetch(`/normal/clusters/${clusterId}/brokers`);
|
||||
};
|
||||
|
||||
export const getClusterDetailThrottles = (clusterId: number) => {
|
||||
return fetch(`/normal/clusters/${clusterId}/throttles`);
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取员工信息
|
||||
*/
|
||||
export const getStaff = (keyword: string) => {
|
||||
const api = `/normal/accounts?keyWord=${keyword}`;
|
||||
const cacheData = apiCache.getDataFromCache(api);
|
||||
if (cacheData) {
|
||||
return new Promise(res => res(cacheData));
|
||||
}
|
||||
return fetch(api).then((data) => {
|
||||
apiCache.setCacheMap(api, data);
|
||||
return data;
|
||||
}).catch(() => {
|
||||
apiCache.deleteDataFromCache(api);
|
||||
return [];
|
||||
});
|
||||
};
|
||||
|
||||
export const userLogin = (params: IUser) => {
|
||||
return fetch('/sso/login', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 应用相关接口
|
||||
*/
|
||||
|
||||
export const getAppList = () => {
|
||||
return fetch(`/normal/apps`);
|
||||
};
|
||||
|
||||
export const modfiyApplication = (params: any) => {
|
||||
return fetch('/normal/apps', {
|
||||
body: JSON.stringify(params),
|
||||
method: 'PUT',
|
||||
});
|
||||
};
|
||||
|
||||
export const getAppDetail = (appId: string) => {
|
||||
return fetch(`/normal/apps/${appId}/basic-info`);
|
||||
};
|
||||
|
||||
export const getAppTopicList = (appId: string, mine: boolean) => {
|
||||
return fetch(`/normal/apps/${appId}/topics?mine=${mine}`);
|
||||
};
|
||||
|
||||
/**
|
||||
* 专家服务
|
||||
*/
|
||||
|
||||
export const getHotTopics = () => {
|
||||
return fetch(`/op/expert/regions/hot-topics`);
|
||||
};
|
||||
|
||||
export const getReassignTasks = () => {
|
||||
return fetch(`/op/reassign-tasks`);
|
||||
};
|
||||
|
||||
export const getTaskTopicMetadata = (clusterId: number) => {
|
||||
return fetch(`/rd/clusters/${clusterId}/topic-metadata`);
|
||||
};
|
||||
|
||||
export const getReassignTasksDetail = (taskId: number) => {
|
||||
return fetch(`/op/reassign-tasks/${taskId}/detail`);
|
||||
};
|
||||
|
||||
export const getReassignTasksStatus = (taskId: number) => {
|
||||
return fetch(`/op/reassign-tasks/${taskId}/status`);
|
||||
};
|
||||
|
||||
export const getInsufficientPartition = () => {
|
||||
return fetch(`/op/expert/topics/insufficient-partitions`);
|
||||
};
|
||||
|
||||
export const createMigrationTask = (params: IMigration[]) => {
|
||||
return fetch(`/op/reassign-tasks`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const getExecuteTask = (params: IExecute) => {
|
||||
return fetch(`/op/reassign-tasks`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const getExecuteSubTask = (params: IExecute) => {
|
||||
return fetch(`/op/reassign-tasks/sub-tasks`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const getExpandTopics = (params: IEepand[]) => {
|
||||
return fetch(`/op/utils/expand-partitions`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const getResourceManagement = () => {
|
||||
return fetch(`/op/expert/topics/expired`);
|
||||
};
|
||||
|
||||
export const getUtilsTopics = (params: IUtils) => {
|
||||
return fetch(`/op/utils/topics`, {
|
||||
method: 'DELETE',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const getAnomalyFlow = (timestamp: number) => {
|
||||
return fetch(`/op/expert/topics/anomaly-flow?timestamp=${timestamp}`);
|
||||
};
|
||||
|
||||
/**
|
||||
* 工单
|
||||
*/
|
||||
|
||||
export const applyOrder = (params: IOrderParams) => {
|
||||
return fetch('/normal/orders', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const getAppsConnections = (appId: string) => {
|
||||
return fetch(`/normal/apps/${appId}/connections`);
|
||||
};
|
||||
|
||||
export const getTopicAppQuota = (clusterId: number, topicName: string) => {
|
||||
return fetch(`/normal/${clusterId}/topics/${topicName}/my-apps`);
|
||||
};
|
||||
|
||||
export const getBrokerMetadata = (clusterId: number) => {
|
||||
return fetch(`/normal/clusters/${clusterId}/broker-metadata`);
|
||||
};
|
||||
|
||||
export const approvalOrder = (params: IApprovalOrder) => {
|
||||
return fetch(`/normal/orders`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 个人中心
|
||||
* @see http://127.0.0.1:8080/swagger-ui.html#!/OP4524037213333045620851255092147540REST41/getOrderAppDetailUsingGET
|
||||
*/
|
||||
export const getOrderTypeList = () => {
|
||||
return fetch('/normal/orders/type-enums') ;
|
||||
};
|
||||
|
||||
// 我的申请
|
||||
export const getApplyOrderList = (status: number) => {
|
||||
return fetch(`/normal/orders?status=${status === 2 ? '' : status}`) ;
|
||||
};
|
||||
|
||||
export const getOrderDetail = (orderId: number) => {
|
||||
return fetch(`/normal/orders/${orderId}/detail`);
|
||||
};
|
||||
|
||||
export const cancelOrder = (id: number) => {
|
||||
return fetch(`/normal/orders?id=${id}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
};
|
||||
|
||||
export const batchApprovalOrders = (params: IBatchApproval) => {
|
||||
return fetch(`/normal/orders/batch`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
// 我的审批
|
||||
export const getApprovalOrderList = (status: number) => {
|
||||
return fetch(`/normal/approvals?status=${status === 2 ? '' : status}`);
|
||||
};
|
||||
|
||||
export const getBrokerBasicInfo = (clusterId: number) => {
|
||||
return fetch(`/rd/clusters/${clusterId}/brokers/basic-info`);
|
||||
};
|
||||
|
||||
// 我的账单
|
||||
|
||||
export const getBillList = (startTime: number, endTime: number) => {
|
||||
return fetch(`/normal/bills/staff-summary?startTime=${startTime}&endTime=${endTime}`);
|
||||
};
|
||||
|
||||
export const getBillDetail = (timestamp: number) => {
|
||||
return fetch(`/normal/bills/staff-detail?timestamp=${timestamp}`);
|
||||
};
|
||||
|
||||
/**
|
||||
* 运维管控
|
||||
*/
|
||||
|
||||
export const getBillStaffSummary = (username: string, startTime: number, endTime: number) => {
|
||||
return fetch(`/rd/bills/${username}/staff-summary?startTime=${startTime}&endTime=${endTime}`);
|
||||
};
|
||||
|
||||
export const getBillStaffDetail = (username: string, timestamp: number) => {
|
||||
return fetch(`/rd/bills/${username}/staff-detail?timestamp=${timestamp}`);
|
||||
};
|
||||
|
||||
export const getTasksKafkaFiles = (clusterId: number) => {
|
||||
return fetch(`/op/cluster-tasks/kafka-files?clusterId=${clusterId}`);
|
||||
};
|
||||
|
||||
export const getMetaData = (needDetail: boolean = true) => {
|
||||
return fetch(`/rd/clusters/basic-info?need-detail=${needDetail}`);
|
||||
};
|
||||
|
||||
export const getConfigure = () => {
|
||||
return fetch(`/rd/configs`);
|
||||
};
|
||||
|
||||
export const addNewConfigure = (params: IConfigure) => {
|
||||
return fetch(`/rd/configs`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const editConfigure = (params: IConfigure) => {
|
||||
return fetch(`/rd/configs`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const deleteConfigure = (configKey: string) => {
|
||||
return fetch(`/rd/configs?config-key=${configKey}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
};
|
||||
|
||||
export const getDataCenter = () => {
|
||||
return fetch(`/normal/configs/idc`);
|
||||
};
|
||||
|
||||
export const deleteCluster = (clusterId: number) => {
|
||||
return fetch(`/op/clusters?clusterId=${clusterId}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
};
|
||||
|
||||
export const createCluster = (params: IRegister) => {
|
||||
return fetch(`/op/clusters`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const registerCluster = (params: IRegister) => {
|
||||
return fetch(`/op/clusters`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const pauseMonitoring = (clusterId: number, status: number) => {
|
||||
return fetch(`/op/clusters/${clusterId}/monitor?status=${status}`, {
|
||||
method: 'PUT',
|
||||
});
|
||||
};
|
||||
|
||||
export const getBasicInfo = (clusterId: number) => {
|
||||
return fetch(`/rd/clusters/${clusterId}/basic-info?need-detail=false`);
|
||||
};
|
||||
|
||||
export const getClusterRealTime = (clusterId: number) => {
|
||||
return fetch(`/rd/clusters/${clusterId}/metrics`);
|
||||
};
|
||||
|
||||
export const getClusterMetrice = (clusterId: number, startTime: string, endTime: string) => {
|
||||
return fetch(`/rd/clusters/${clusterId}/metrics-history?startTime=${startTime}&endTime=${endTime}`);
|
||||
};
|
||||
|
||||
export const getClusterTopics = (clusterId: number) => {
|
||||
return fetch(`/rd/clusters/${clusterId}/topics`);
|
||||
};
|
||||
|
||||
export const getTopicsBasicInfo = (clusterId: number, topicName: string) => {
|
||||
return fetch(`/rd/${clusterId}/topics/${topicName}/basic-info`);
|
||||
};
|
||||
|
||||
export const editTopic = (params: IEditTopic) => {
|
||||
return fetch(`/op/utils/topics`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const expandPartition = (params: IExpand[]) => {
|
||||
return fetch(`/op/utils/expand-partitions`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const deleteClusterTopic = (params: IDeleteTopic[]) => {
|
||||
return fetch(`/op/utils/topics`, {
|
||||
method: 'DELETE',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const getClusterBroker = (clusterId: number) => {
|
||||
return fetch(`/rd/clusters/${clusterId}/brokers`);
|
||||
};
|
||||
|
||||
export const getClusterConsumer = (clusterId: number) => {
|
||||
return fetch(`/rd/${clusterId}/consumer-groups`);
|
||||
};
|
||||
|
||||
export const getConsumerDetails = (clusterId: number, consumerGroup: string, location: string) => {
|
||||
// tslint:disable-next-line:max-line-length
|
||||
return fetch(`/rd/${clusterId}/consumer-groups/${consumerGroup}/topics?location=${location}`);
|
||||
};
|
||||
|
||||
export const getControllerHistory = (clusterId: number) => {
|
||||
return fetch(`/rd/clusters/${clusterId}/controller-history`);
|
||||
};
|
||||
|
||||
/**
|
||||
* 运维管控 broker
|
||||
*/
|
||||
|
||||
export const getBrokersBasicInfo = (clusterId: number, brokerId: number) => {
|
||||
return fetch(`/rd/${clusterId}/brokers/${brokerId}/basic-info`);
|
||||
};
|
||||
|
||||
export const getPeakFlowStatus = () => {
|
||||
return fetch(`/normal/configs/peak-flow-status`);
|
||||
};
|
||||
|
||||
export const getBrokersStatus = (clusterId: number) => {
|
||||
return fetch(`/rd/clusters/${clusterId}/brokers-status`);
|
||||
};
|
||||
|
||||
export const getBrokersMetrics = (clusterId: number, brokerId: number) => {
|
||||
return fetch(`/rd/${clusterId}/brokers/${brokerId}/metrics`);
|
||||
};
|
||||
|
||||
export const getBrokersMetricsHistory = (clusterId: number, brokerId: number, startTime: string, endTime: string) => {
|
||||
return fetch(`/rd/${clusterId}/brokers/${brokerId}/metrics-history?startTime=${startTime}&endTime=${endTime}`);
|
||||
};
|
||||
|
||||
export const getBrokersTopics = (clusterId: number, brokerId: number) => {
|
||||
return fetch(`/rd/${clusterId}/brokers/${brokerId}/topics`);
|
||||
};
|
||||
|
||||
export const getBrokersPartitions = (clusterId: number, brokerId: number) => {
|
||||
return fetch(`/rd/${clusterId}/brokers/${brokerId}/partitions`);
|
||||
};
|
||||
|
||||
export const getBrokersAnalysis = (clusterId: number, brokerId: number) => {
|
||||
return fetch(`/rd/${clusterId}/brokers/${brokerId}/analysis`);
|
||||
};
|
||||
|
||||
export const getBrokersMetadata = (clusterId: number) => {
|
||||
return fetch(`/rd/${clusterId}/brokers/broker-metadata`);
|
||||
};
|
||||
|
||||
export const getBrokersRegions = (clusterId: number) => {
|
||||
return fetch(`/rd/${clusterId}/regions`);
|
||||
};
|
||||
|
||||
export const getLogicalClusters = (clusterId: number) => {
|
||||
return fetch(`/rd/${clusterId}/logical-clusters`);
|
||||
};
|
||||
|
||||
export const queryLogicalClusters = (logicalClusterId: number) => {
|
||||
return fetch(`/rd/logical-clusters?id=${logicalClusterId}`);
|
||||
};
|
||||
|
||||
export const createLogicalClusters = (params: INewLogical) => {
|
||||
return fetch(`/rd/logical-clusters`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const editLogicalClusters = (params: INewLogical) => {
|
||||
return fetch(`/rd/logical-clusters`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const deteleLogicalClusters = (logicalClusterId: number) => {
|
||||
return fetch(`/rd/logical-clusters?id=${logicalClusterId}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
};
|
||||
|
||||
export const deteleClusterBrokers = (clusterId: number, brokerId: number) => {
|
||||
return fetch(`/rd/${clusterId}/brokers?brokerId=${brokerId}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
};
|
||||
|
||||
export const getStaffSummary = (timestamp: number) => {
|
||||
return fetch(`/rd/bills/staff-summary?timestamp=${timestamp}`);
|
||||
};
|
||||
|
||||
export const addNewRegions = (params: INewRegions) => {
|
||||
return fetch(`/rd/regions`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const editRegions = (params: INewRegions) => {
|
||||
return fetch(`/rd/regions`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const deleteRegions = (params: number) => {
|
||||
return fetch(`/rd/regions?id=${params}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
};
|
||||
|
||||
export const implementRegions = (params: IRebalance) => {
|
||||
return fetch(`/op/utils/rebalance`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const rebalanceStatus = (clusterId: number) => {
|
||||
return fetch(`/op/utils/rebalance-status?clusterId=${clusterId}`);
|
||||
};
|
||||
|
||||
export const getClustersThrottles = (clusterId: number) => {
|
||||
return fetch(`/rd/clusters/${clusterId}/throttles`);
|
||||
};
|
||||
|
||||
export const getPartitionsLocation = (clusterId: number, brokerId: number) => {
|
||||
return fetch(`/rd/${clusterId}/brokers/${brokerId}/partitions-location`);
|
||||
};
|
||||
|
||||
/**
|
||||
* 运维管控 任务管理
|
||||
*/
|
||||
|
||||
export const getConfigsTaskStatus = () => {
|
||||
return fetch(`/normal/configs/task-status`);
|
||||
};
|
||||
|
||||
export const getTaskManagement = () => {
|
||||
return fetch(`/op/cluster-tasks`);
|
||||
};
|
||||
|
||||
export const getClusterTasksEnums = () => {
|
||||
return fetch(`/op/cluster-tasks/enums`);
|
||||
};
|
||||
|
||||
export const getConfigsKafkaRoles = () => {
|
||||
return fetch(`/rd/configs/kafka-roles`);
|
||||
};
|
||||
|
||||
export const newlyBuildEcmTasks = (params: INewBulidEnums) => {
|
||||
return fetch(`/op/cluster-tasks`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const getTasksMetadata = (taskId: number) => {
|
||||
return fetch(`/op/cluster-tasks/${taskId}/metadata`);
|
||||
};
|
||||
|
||||
export const triggerClusterTask = (params: ITrigger) => {
|
||||
return fetch(`/op/cluster-tasks`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const getSubtasksStatus = (taskId: number) => {
|
||||
return fetch(`/op/cluster-tasks/${taskId}/status`);
|
||||
};
|
||||
|
||||
export const getClusterTaskLog = (taskId: number, hostname: string) => {
|
||||
return fetch(`/op/cluster-tasks/${taskId}/log?hostname=${hostname}`);
|
||||
};
|
||||
|
||||
/**
|
||||
* 运维管控 用户管理
|
||||
*/
|
||||
|
||||
export const getUserList = () => {
|
||||
return fetch('/rd/accounts');
|
||||
};
|
||||
|
||||
export const modfiyUser = (params: IUser) => {
|
||||
return fetch('/rd/accounts', {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const addUser = (params: IUser) => {
|
||||
return fetch('/rd/accounts', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const deleteUser = (username: string) => {
|
||||
return fetch(`/rd/accounts?username=${username}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 运维管控 版本管理
|
||||
*/
|
||||
|
||||
export const getFileList = () => {
|
||||
return fetch('/rd/kafka-files');
|
||||
};
|
||||
|
||||
export const modfiyFile = (params: IUploadFile) => {
|
||||
const { file, id, description, fileName, fileMd5 } = params;
|
||||
const formData = new FormData();
|
||||
formData.append('uploadFile', file);
|
||||
formData.append('description', description);
|
||||
formData.append('fileName', fileName);
|
||||
formData.append('fileMd5', fileMd5);
|
||||
formData.append('id', id + '');
|
||||
|
||||
return formFetch('/rd/kafka-files?modify=true', {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
});
|
||||
};
|
||||
|
||||
export const addFile = (params: IUploadFile) => {
|
||||
const { file, fileType, description, fileName, clusterId, fileMd5 } = params;
|
||||
const formData = new FormData();
|
||||
formData.append('uploadFile', file);
|
||||
formData.append('fileType', fileType + '');
|
||||
formData.append('fileName', fileName);
|
||||
formData.append('clusterId', clusterId + '');
|
||||
formData.append('description', description);
|
||||
formData.append('fileMd5', fileMd5);
|
||||
|
||||
return formFetch('/rd/kafka-files', {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
});
|
||||
};
|
||||
|
||||
export const deleteFile = (id: number) => {
|
||||
return fetch(`/rd/kafka-files?id=${id}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
};
|
||||
|
||||
export const getFileType = () => {
|
||||
return fetch('/rd/kafka-files/enums');
|
||||
};
|
||||
|
||||
export const getConfigFiles = (fileId: number) => {
|
||||
return fetch(`/rd/kafka-files/${fileId}/config-files`);
|
||||
};
|
||||
|
||||
/**
|
||||
* 运维管控 应用管理
|
||||
*/
|
||||
export const getAdminAppList = () => {
|
||||
return fetch(`/rd/apps`);
|
||||
};
|
||||
|
||||
export const modfiyAdminApp = (params: any) => {
|
||||
return fetch('/rd/apps', {
|
||||
body: JSON.stringify(params),
|
||||
method: 'PUT',
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* sso api
|
||||
*/
|
||||
|
||||
export const getTicketBycode = (code: string) => {
|
||||
return fetch('/sso/opensource/login', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ code }),
|
||||
});
|
||||
};
|
||||
|
||||
export const userLogOut = () => {
|
||||
return fetch('/sso/logout', {
|
||||
method: 'DELETE',
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 监控报警 alarm
|
||||
*/
|
||||
|
||||
export const getMonitorStrategies = () => {
|
||||
return fetch('/normal/monitor-strategies');
|
||||
};
|
||||
|
||||
export const deteleMonitorStrategies = (monitorId: number) => {
|
||||
return fetch(`/normal/monitor-strategies?monitorId=${monitorId}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
};
|
||||
|
||||
export const getMonitorAlerts = (monitorId: number, startTime: number, endTime: number) => {
|
||||
return fetch(`/normal/monitor-alerts?monitorId=${monitorId}&startTime=${startTime}&endTime=${endTime}`);
|
||||
};
|
||||
|
||||
export const getAlertsDetail = (alertId: number) => {
|
||||
return fetch(`/normal/monitor-alerts/${alertId}/detail`);
|
||||
};
|
||||
|
||||
export const createSilences = (params: IMonitorSilences) => {
|
||||
return fetch(`/normal/monitor-silences`, {
|
||||
body: JSON.stringify(params),
|
||||
method: 'POST',
|
||||
});
|
||||
};
|
||||
|
||||
export const getMonitorSilences = (monitorId: number) => {
|
||||
return fetch(`/normal/monitor-silences?monitorId=${monitorId}`);
|
||||
};
|
||||
|
||||
export const modifyMask = (params: IMonitorSilences) => {
|
||||
return fetch('/normal/monitor-silences', {
|
||||
body: JSON.stringify(params),
|
||||
method: 'PUT',
|
||||
});
|
||||
};
|
||||
|
||||
export const getSilencesDetail = (silenceId: number) => {
|
||||
return fetch(`/normal/monitor-silences/${silenceId}/detail`);
|
||||
};
|
||||
|
||||
export const deleteSilences = (monitorId: number, silenceId: number) => {
|
||||
return fetch(`/normal/monitor-silences?monitorId=${monitorId}&silenceId=${silenceId}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
};
|
||||
export const getMonitorType = () => {
|
||||
return fetch('/normal/monitor-enums');
|
||||
};
|
||||
|
||||
export const addMonitorStrategy = (params: IRequestParams) => {
|
||||
return fetch('/normal/monitor-strategies', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const getMonitorDetail = (monitorId: number) => {
|
||||
return fetch(`/normal/monitor-strategies/${monitorId}/detail`);
|
||||
};
|
||||
|
||||
export const modifyMonitorStrategy = (params: IRequestParams) => {
|
||||
return fetch('/normal/monitor-strategies', {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const getMonitorNotifyGroups = () => {
|
||||
return fetch(`/normal/monitor-notify-groups`);
|
||||
};
|
||||
91
kafka-manager-console/src/lib/bar-pie-config.ts
Normal file
91
kafka-manager-console/src/lib/bar-pie-config.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
import { ILabelValue, IBill } from 'types/base-type';
|
||||
|
||||
export const getBillBarOption = (data: IBill[]) => {
|
||||
const xData: string[] = [];
|
||||
const yData: number[] = [];
|
||||
|
||||
if (data) {
|
||||
data.forEach(item => {
|
||||
xData.push(item.gmtMonth);
|
||||
yData.push(item.cost);
|
||||
});
|
||||
}
|
||||
return {
|
||||
color: ['#3398DB'],
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: { // 坐标轴指示器,坐标轴触发有效
|
||||
type: 'line', // 默认为直线,可选为:'line' | 'shadow'
|
||||
},
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
type: 'category',
|
||||
data: xData,
|
||||
axisTick: {
|
||||
alignWithLabel: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
yAxis: [
|
||||
{
|
||||
type: 'value',
|
||||
},
|
||||
],
|
||||
grid: {
|
||||
left: '1%',
|
||||
right: '1%',
|
||||
bottom: '3%',
|
||||
top: '40px',
|
||||
containLabel: true,
|
||||
},
|
||||
series: yData.length ? [
|
||||
{
|
||||
name: '金额',
|
||||
type: 'bar',
|
||||
barWidth: '60%',
|
||||
data: yData,
|
||||
},
|
||||
] : null,
|
||||
};
|
||||
};
|
||||
|
||||
export const getPieChartOption = (data: ILabelValue[], legend: string[]) => {
|
||||
const color = legend.length > 2 ? ['#4BD863', '#3399ff', '#F19736', '#F04844', '#999999'] : ['#F28E61', '#7082A6'];
|
||||
return {
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{a} <br/>{b}: {c} ({d}%)',
|
||||
},
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
right: 10,
|
||||
top: '35%',
|
||||
data: legend,
|
||||
},
|
||||
color,
|
||||
series: data && data.length ? [
|
||||
{
|
||||
name: '',
|
||||
type: 'pie',
|
||||
radius: ['50%', '35%'],
|
||||
avoidLabelOverlap: false,
|
||||
label: {
|
||||
show: false,
|
||||
position: 'center',
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
show: true,
|
||||
fontSize: '16',
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
},
|
||||
labelLine: {
|
||||
show: false,
|
||||
},
|
||||
data,
|
||||
},
|
||||
] : [],
|
||||
};
|
||||
};
|
||||
111
kafka-manager-console/src/lib/chart-utils.ts
Normal file
111
kafka-manager-console/src/lib/chart-utils.ts
Normal file
@@ -0,0 +1,111 @@
|
||||
import { ISeriesOption } from 'types/base-type';
|
||||
|
||||
export const isArrElementAllNull = (arr: any[]) => {
|
||||
let isAllNull = true;
|
||||
arr.forEach(item => {
|
||||
if (item !== null) {
|
||||
isAllNull = false;
|
||||
}
|
||||
});
|
||||
return isAllNull;
|
||||
};
|
||||
|
||||
export const dealFlowData = (metricList: string[], data: any[]) => {
|
||||
let name = '';
|
||||
const metricData = [] as Array<{
|
||||
metric: string,
|
||||
data: number[],
|
||||
}>;
|
||||
metricList.map(metric => {
|
||||
metricData.push({
|
||||
metric,
|
||||
data: data.map(item => item[metric]),
|
||||
});
|
||||
});
|
||||
|
||||
if (metricData.map(i => isMB(i.data)).some(i => i === true)) {
|
||||
name = 'MB/s';
|
||||
metricList.map(metric => {
|
||||
data.map(item => {
|
||||
item[metric] = item[metric] !== null ? Number((item[metric] / (1024 * 1024)).toFixed(2)) : null;
|
||||
});
|
||||
});
|
||||
} else if (metricData.map(i => isKB(i.data)).some(i => i === true)) {
|
||||
name = 'KB/s';
|
||||
metricList.map(metric => {
|
||||
data.map(item => {
|
||||
item[metric] = item[metric] !== null ? Number((item[metric] / (1024)).toFixed(2)) : null;
|
||||
});
|
||||
});
|
||||
} else {
|
||||
name = 'B/s';
|
||||
metricList.map(metric => {
|
||||
data.map(item => {
|
||||
item[metric] = item[metric] !== null ? Number(item[metric].toFixed(2)) : null;
|
||||
});
|
||||
});
|
||||
}
|
||||
return { name, data };
|
||||
};
|
||||
|
||||
export function isMB(arr: number[]) {
|
||||
const filterData = arr.filter(i => i !== 0);
|
||||
if (filterData.length) return filterData.reduce((cur, pre) => cur + pre) / filterData.length >= 100000;
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isKB(arr: number[]) {
|
||||
const filterData = arr.filter(i => i !== 0);
|
||||
if (filterData.length) return filterData.reduce((cur, pre) => cur + pre) / filterData.length >= 1000;
|
||||
return false;
|
||||
}
|
||||
|
||||
export const getFilterSeries = (series: ISeriesOption[]) => {
|
||||
const filterSeries = [].concat(...series);
|
||||
const nullIndex: string[] = [];
|
||||
for (const row of series) {
|
||||
if (isArrElementAllNull(row.data)) {
|
||||
nullIndex.push(row.name);
|
||||
}
|
||||
}
|
||||
|
||||
nullIndex.map(line => {
|
||||
const index = filterSeries.findIndex(row => row.name === line);
|
||||
if (index > -1) {
|
||||
filterSeries.splice(index, 1);
|
||||
}
|
||||
});
|
||||
for (const item of filterSeries) {
|
||||
delete item.data;
|
||||
}
|
||||
return filterSeries;
|
||||
};
|
||||
|
||||
export const baseLineConfig = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
padding: 10,
|
||||
backgroundColor: 'rgba(0,0,0,0.7)',
|
||||
borderColor: '#333',
|
||||
textStyle: {
|
||||
color: '#f3f3f3',
|
||||
fontSize: 10,
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
nameLocation: 'end',
|
||||
nameGap: 10,
|
||||
},
|
||||
legend: {
|
||||
right: '1%',
|
||||
top: '10px',
|
||||
},
|
||||
grid: {
|
||||
left: '1%',
|
||||
right: '1%',
|
||||
bottom: '3%',
|
||||
top: '40px',
|
||||
containLabel: true,
|
||||
},
|
||||
};
|
||||
133
kafka-manager-console/src/lib/fetch.ts
Normal file
133
kafka-manager-console/src/lib/fetch.ts
Normal file
@@ -0,0 +1,133 @@
|
||||
import { notification } from 'component/antd';
|
||||
import { region } from 'store';
|
||||
import { urlPrefix } from 'constants/left-menu';
|
||||
import Url from 'lib/url-parser';
|
||||
|
||||
const window = self.window;
|
||||
|
||||
export interface IRes {
|
||||
code: number;
|
||||
message: string;
|
||||
data: any;
|
||||
}
|
||||
|
||||
const checkStatus = (res: Response) => {
|
||||
if (res.status === 401) {
|
||||
let location = `${window.location.host}${urlPrefix}/login`;
|
||||
if (!/^http(s)?:\/\//.test(location)) {
|
||||
location = `${window.location.protocol}//${location}`;
|
||||
}
|
||||
|
||||
const jumpto = window.location.href.includes('login') ? urlPrefix : window.location.href;
|
||||
window.location.href = `${location}?jumpto=${encodeURIComponent(jumpto)}`;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// if (res.status === 403) {
|
||||
// window.location.href = window.location.origin + `${urlPrefix}/error`;
|
||||
// return res;
|
||||
// }
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
const filter = (init: IInit) => (res: IRes) => {
|
||||
if (res.code !== 0 && res.code !== 200) {
|
||||
if (!init.errorNoTips) {
|
||||
notification.error({
|
||||
message: '错误',
|
||||
description: res.message || '服务器错误,请重试!',
|
||||
});
|
||||
}
|
||||
throw res;
|
||||
}
|
||||
|
||||
return res.data;
|
||||
};
|
||||
|
||||
const prefix = '/api/v1';
|
||||
|
||||
interface IInit extends RequestInit {
|
||||
errorNoTips?: boolean;
|
||||
body?: BodyInit | null | any;
|
||||
}
|
||||
|
||||
const csrfTokenMethod = ['POST', 'PUT', 'DELETE'];
|
||||
|
||||
const addCustomHeader = (init?: IInit) => {
|
||||
init.headers = Object.assign(init.headers || {}, {
|
||||
'X-Data-Center': region.currentRegion,
|
||||
'X_Project_Type': 'open',
|
||||
});
|
||||
return init;
|
||||
};
|
||||
|
||||
const addExtraParameters = (url: string, init?: IInit) => {
|
||||
const isPhysical = Url().search.hasOwnProperty('isPhysicalClusterId');
|
||||
|
||||
if (!init.method) { // GET
|
||||
url = isPhysical ?
|
||||
// tslint:disable-next-line:max-line-length
|
||||
url.indexOf('?') > 0 ? `${url}&isPhysicalClusterId=true&dataCenter=${region.currentRegion}` : `${url}?isPhysicalClusterId=true&dataCenter=${region.currentRegion}`
|
||||
: url.indexOf('?') > 0 ? `${url}&dataCenter=${region.currentRegion}` : `${url}?dataCenter=${region.currentRegion}`;
|
||||
} else {
|
||||
const params = isPhysical ? { dataCenter: region.currentRegion, isPhysicalClusterId: true } : { dataCenter: region.currentRegion };
|
||||
if (init.body) {
|
||||
const body = JSON.parse(init.body);
|
||||
Object.assign(body, params);
|
||||
init.body = JSON.stringify(body);
|
||||
} else {
|
||||
init.body = JSON.stringify(params);
|
||||
}
|
||||
}
|
||||
|
||||
init = addCustomHeader(init);
|
||||
return { url, init };
|
||||
};
|
||||
|
||||
export default function fetch(url: string, init?: IInit) {
|
||||
if (!init) init = {};
|
||||
|
||||
if (!init.credentials) init.credentials = 'include';
|
||||
if (init.body && typeof init.body === 'object') init.body = JSON.stringify(init.body);
|
||||
if (init.body && !init.method) init.method = 'POST';
|
||||
if (init.method) init.method = init.method.toUpperCase();
|
||||
|
||||
if (csrfTokenMethod.includes(init.method)) {
|
||||
init.headers = Object.assign({}, init.headers || {
|
||||
'Content-Type': 'application/json',
|
||||
});
|
||||
}
|
||||
|
||||
const { url: reqUrl, init: reqInit } = addExtraParameters(url, init);
|
||||
let realUrl = reqUrl;
|
||||
|
||||
if (!/^http(s)?:\/\//.test(reqUrl)) {
|
||||
realUrl = `${prefix}${reqUrl}`;
|
||||
}
|
||||
|
||||
return window
|
||||
.fetch(realUrl, reqInit)
|
||||
.then(res => checkStatus(res))
|
||||
.then((res) => res.json())
|
||||
.then(filter(reqInit));
|
||||
}
|
||||
|
||||
export function formFetch(url: string, init?: IInit) {
|
||||
url = url.indexOf('?') > 0 ?
|
||||
`${url}&dataCenter=${region.currentRegion}` : `${url}?dataCenter=${region.currentRegion}`;
|
||||
let realUrl = url;
|
||||
|
||||
if (!/^http(s)?:\/\//.test(url)) {
|
||||
realUrl = `${prefix}${url}`;
|
||||
}
|
||||
|
||||
init = addCustomHeader(init);
|
||||
|
||||
return window
|
||||
.fetch(realUrl, init)
|
||||
.then(res => checkStatus(res))
|
||||
.then((res) => res.json())
|
||||
.then(filter(init));
|
||||
}
|
||||
414
kafka-manager-console/src/lib/line-charts-config.ts
Normal file
414
kafka-manager-console/src/lib/line-charts-config.ts
Normal file
@@ -0,0 +1,414 @@
|
||||
import { ISeriesOption, IMetricPoint, IOptionType, ITakeType, IClusterMetrics, ITakeMetric } from 'types/base-type';
|
||||
import { metricOptionMap } from 'constants/status-map';
|
||||
import moment = require('moment');
|
||||
import { timeFormat } from 'constants/strategy';
|
||||
import { getFilterSeries, baseLineConfig, dealFlowData } from './chart-utils';
|
||||
|
||||
type IMetricType = {
|
||||
[key in IOptionType | IOptionType]: string[];
|
||||
};
|
||||
|
||||
interface IMetric {
|
||||
type: string;
|
||||
arr: string[];
|
||||
}
|
||||
|
||||
interface IData {
|
||||
[key: string]: number;
|
||||
}
|
||||
|
||||
interface ISeriesCoord {
|
||||
coord: any[];
|
||||
}
|
||||
|
||||
const metricTypeMap: IMetricType = {
|
||||
'byteIn/byteOut': ['bytesInPerSec', 'bytesOutPerSec'],
|
||||
'messageIn': ['messagesInPerSec'],
|
||||
// tslint:disable-next-line:max-line-length
|
||||
'byteIn/byteOut/appByteIn/appByteOut': ['bytesInPerSec', 'bytesOutPerSec', 'appIdBytesInPerSec', 'appIdBytesOutPerSec'],
|
||||
'messageIn/totalProduceRequests': ['messagesInPerSec', 'totalProduceRequestsPerSec'],
|
||||
'byteRejected': ['bytesRejectedPerSec'],
|
||||
'topicNum': ['topicNum'],
|
||||
'brokerNum': ['brokerNum'],
|
||||
};
|
||||
|
||||
const lengendType = {
|
||||
requestTime99thPercentile: ['fetchRequestTime99thPercentile', 'produceRequestTime99thPercentile'],
|
||||
requestTime95thPercentile: ['fetchRequestTime95thPercentile', 'produceRequestTime95thPercentile'],
|
||||
requestTime75thPercentile: ['fetchRequestTime75thPercentile', 'produceRequestTime75thPercentile'],
|
||||
requestTime50thPercentile: ['fetchRequestTime50thPercentile', 'produceRequestTime50thPercentile'],
|
||||
};
|
||||
|
||||
export const getControlMetricOption = (type: IOptionType, data: IClusterMetrics[]) => {
|
||||
let name;
|
||||
let series: ISeriesOption[];
|
||||
data = data || [];
|
||||
data = data.map(item => {
|
||||
return {
|
||||
time: moment(item.gmtCreate).format(timeFormat),
|
||||
...item,
|
||||
};
|
||||
});
|
||||
const legend = metricTypeMap[type] || [type];
|
||||
series = Array.from(legend, (item: IOptionType) => ({
|
||||
id: item,
|
||||
name: item,
|
||||
type: 'line',
|
||||
symbol: 'circle',
|
||||
showSymbol: false,
|
||||
smooth: true,
|
||||
encode: {
|
||||
x: 'time',
|
||||
y: item,
|
||||
tooltip: [
|
||||
item,
|
||||
],
|
||||
},
|
||||
data: data.map(i => {
|
||||
const seriesType = item as keyof IClusterMetrics;
|
||||
return i[seriesType] !== null ? Number(i[seriesType]) : null;
|
||||
}),
|
||||
}));
|
||||
switch (type) {
|
||||
case 'byteRejected':
|
||||
name = 'B/s';
|
||||
break;
|
||||
case 'messageIn':
|
||||
name = '条';
|
||||
data.map(item => {
|
||||
item.messagesInPerSec = item.messagesInPerSec !== null ? Number(item.messagesInPerSec.toFixed(2)) : null;
|
||||
});
|
||||
break;
|
||||
case 'brokerNum':
|
||||
case 'topicNum':
|
||||
name = '个';
|
||||
break;
|
||||
default:
|
||||
const { name: unitName, data: xData } = dealFlowData(metricTypeMap[type], data);
|
||||
name = unitName;
|
||||
data = xData;
|
||||
break;
|
||||
}
|
||||
const filterSeries = getFilterSeries(series);
|
||||
return {
|
||||
...baseLineConfig,
|
||||
xAxis: {
|
||||
type: 'time',
|
||||
splitLine: false,
|
||||
},
|
||||
yAxis: {
|
||||
...baseLineConfig.yAxis,
|
||||
name,
|
||||
},
|
||||
legend: {
|
||||
data: legend,
|
||||
...baseLineConfig.legend,
|
||||
},
|
||||
dataset: {
|
||||
source: data,
|
||||
},
|
||||
series: filterSeries,
|
||||
};
|
||||
};
|
||||
|
||||
export const clusterMetricOption = (type: string, record: IData[], metricMap: IMetric[]) => {
|
||||
const metrics = record;
|
||||
let field = [] as string[];
|
||||
const ele = metricMap.find((ele: IMetric) => ele.type === type);
|
||||
if (ele) {
|
||||
field = ele.arr;
|
||||
}
|
||||
if (!field.length) { // 表示metricMap中无比对项
|
||||
return record;
|
||||
}
|
||||
const metricOption = [] as any;
|
||||
metrics.forEach((ele: any) => {
|
||||
let nullAmount = 0;
|
||||
field.forEach(e => {
|
||||
if (ele[e] === null) {
|
||||
++nullAmount;
|
||||
}
|
||||
});
|
||||
if (nullAmount !== field.length) {
|
||||
metricOption.push(ele);
|
||||
}
|
||||
});
|
||||
|
||||
return metricOption;
|
||||
};
|
||||
|
||||
const addMarkPoint = (series: ISeriesOption[], data: IClusterMetrics[], unitName: string) => {
|
||||
const markPoint = {
|
||||
symbol: 'pin',
|
||||
symbolSize: 12,
|
||||
itemStyle: {
|
||||
color: '#ff0000',
|
||||
},
|
||||
};
|
||||
|
||||
const dataMap = {
|
||||
fetch: [] as ISeriesCoord[],
|
||||
produce: [] as ISeriesCoord[],
|
||||
};
|
||||
|
||||
data.map((item) => {
|
||||
if (item.produceThrottled && item.appIdBytesInPerSec) {
|
||||
dataMap.produce.push({
|
||||
coord: [moment(item.gmtCreate).format(timeFormat), item.appIdBytesInPerSec],
|
||||
});
|
||||
}
|
||||
if (item.consumeThrottled && item.appIdBytesOutPerSec) {
|
||||
dataMap.fetch.push({
|
||||
coord: [moment(item.gmtCreate).format(timeFormat), item.appIdBytesOutPerSec],
|
||||
});
|
||||
}
|
||||
return item;
|
||||
});
|
||||
|
||||
series = series.map(item => {
|
||||
if (item.name === 'appIdBytesOutPerSec') {
|
||||
item.markPoint = Object.assign({}, markPoint);
|
||||
item.markPoint.data = dataMap.fetch;
|
||||
return item;
|
||||
}
|
||||
if (item.name === 'appIdBytesInPerSec') {
|
||||
item.markPoint = Object.assign({}, markPoint);
|
||||
item.markPoint.data = dataMap.produce;
|
||||
return item;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
};
|
||||
|
||||
export const getClusterMetricOption = (type: IOptionType, record: IClusterMetrics[]) => {
|
||||
let data = clusterMetricOption(type, record, metricOptionMap) as IClusterMetrics[];
|
||||
let name;
|
||||
let series: ISeriesOption[];
|
||||
|
||||
data = data.map(item => {
|
||||
return {
|
||||
time: moment(item.gmtCreate).format(timeFormat),
|
||||
...item,
|
||||
};
|
||||
});
|
||||
data = data.sort((a, b) => a.gmtCreate - b.gmtCreate);
|
||||
const legend = metricTypeMap[type] || [type];
|
||||
series = Array.from(legend, (item: string) => ({
|
||||
id: item,
|
||||
name: item,
|
||||
type: 'line',
|
||||
symbol: 'circle',
|
||||
showSymbol: false,
|
||||
smooth: true,
|
||||
encode: {
|
||||
x: 'time',
|
||||
y: item,
|
||||
tooltip: [
|
||||
item,
|
||||
],
|
||||
},
|
||||
data: data.map((i: any) => {
|
||||
const seriesType = item as keyof IClusterMetrics;
|
||||
|
||||
return i[seriesType] !== null ? Number(i[seriesType]) : null;
|
||||
}),
|
||||
}));
|
||||
switch (type) {
|
||||
case 'byteRejected':
|
||||
name = 'B/s';
|
||||
break;
|
||||
case 'messageIn/totalProduceRequests':
|
||||
name = 'QPS';
|
||||
break;
|
||||
case 'messageIn':
|
||||
name = '条';
|
||||
data.map(item => {
|
||||
item.messagesInPerSec = item.messagesInPerSec !== null ? Number(item.messagesInPerSec.toFixed(2)) : null;
|
||||
});
|
||||
break;
|
||||
default:
|
||||
const { name: unitName, data: xData } = dealFlowData(metricTypeMap[type], data);
|
||||
name = unitName;
|
||||
data = xData;
|
||||
break;
|
||||
}
|
||||
|
||||
const filterSeries = getFilterSeries(series);
|
||||
if (type === 'byteIn/byteOut/appByteIn/appByteOut') {
|
||||
addMarkPoint(series, data, name);
|
||||
}
|
||||
|
||||
return {
|
||||
...baseLineConfig,
|
||||
tooltip: {
|
||||
...baseLineConfig.tooltip,
|
||||
formatter: (params: any) => {
|
||||
let result = params[0].data.time + '<br>';
|
||||
params.forEach((item: any) => {
|
||||
const unitSeries = item.data[item.seriesName] !== null ? Number(item.data[item.seriesName]) : null;
|
||||
// tslint:disable-next-line:max-line-length
|
||||
result += '<span style="display:inline-block;margin-right:0px;border-radius:10px;width:9px;height:9px;background-color:' + item.color + '"></span>';
|
||||
if ( (item.data.produceThrottled && item.seriesName === 'appIdBytesInPerSec')
|
||||
|| (item.data.consumeThrottled && item.seriesName === 'appIdBytesOutPerSec') ) {
|
||||
return result += item.seriesName + ': ' + unitSeries + '(被限流)' + '<br>';
|
||||
}
|
||||
return result += item.seriesName + ': ' + unitSeries + '<br>';
|
||||
});
|
||||
return result;
|
||||
},
|
||||
},
|
||||
xAxis: {
|
||||
type: 'time',
|
||||
splitLine: false,
|
||||
},
|
||||
legend: {
|
||||
...baseLineConfig.legend,
|
||||
data: legend,
|
||||
},
|
||||
yAxis: {
|
||||
...baseLineConfig.yAxis,
|
||||
name,
|
||||
},
|
||||
dataset: {
|
||||
source: data,
|
||||
},
|
||||
series: filterSeries,
|
||||
};
|
||||
};
|
||||
|
||||
export const getMonitorMetricOption = (seriesName: string, data: IMetricPoint[]) => {
|
||||
let series: ISeriesOption[];
|
||||
data = data || [];
|
||||
data = data.map(item => {
|
||||
return {
|
||||
...item,
|
||||
time: moment(item.timestamp * 1000).format(timeFormat),
|
||||
};
|
||||
});
|
||||
|
||||
series = [{
|
||||
name: seriesName,
|
||||
type: 'line',
|
||||
symbol: 'circle',
|
||||
id: seriesName,
|
||||
showSymbol: false,
|
||||
smooth: true,
|
||||
encode: {
|
||||
x: 'time',
|
||||
y: 'value',
|
||||
tooltip: [
|
||||
'value',
|
||||
],
|
||||
},
|
||||
data: data.map(i => {
|
||||
return i.value !== null ? Number(i.value) : null;
|
||||
}),
|
||||
}];
|
||||
const filterSeries = getFilterSeries(series);
|
||||
|
||||
return {
|
||||
...baseLineConfig,
|
||||
tooltip: {
|
||||
...baseLineConfig.tooltip,
|
||||
formatter: (params: any) => {
|
||||
let result = params[0].value.time + '<br>';
|
||||
params.forEach((item: any) => {
|
||||
series.forEach((ele: any) => {
|
||||
if (ele.name === item.seriesName) {
|
||||
// tslint:disable-next-line:max-line-length
|
||||
result += '<span style="display:inline-block;margin-right:0px;border-radius:10px;width:9px;height:9px;background-color:' + item.color + '"></span>';
|
||||
return result += item.seriesName + ': ' + (item.data.value === null ? '' : item.data.value.toFixed(2)) + '<br>';
|
||||
}
|
||||
});
|
||||
});
|
||||
return result;
|
||||
},
|
||||
},
|
||||
xAxis: {
|
||||
type: 'time',
|
||||
splitLine: false,
|
||||
},
|
||||
yAxis: {
|
||||
...baseLineConfig.yAxis,
|
||||
},
|
||||
dataset: {
|
||||
source: data,
|
||||
},
|
||||
series: filterSeries,
|
||||
};
|
||||
};
|
||||
|
||||
export const getClusterMetricTake = (type: ITakeType, data: ITakeMetric[]) => {
|
||||
let series: ISeriesOption[];
|
||||
data = data || [];
|
||||
|
||||
let legend = [] as string[];
|
||||
for (const key in lengendType) {
|
||||
if (key === type) {
|
||||
legend = lengendType[key];
|
||||
}
|
||||
}
|
||||
data = data.map(item => {
|
||||
return {
|
||||
time: moment(item.gmtCreate).format(timeFormat),
|
||||
...item,
|
||||
};
|
||||
});
|
||||
|
||||
series = Array.from(legend, (item: ITakeType) => ({
|
||||
id: item,
|
||||
name: item,
|
||||
type: 'line',
|
||||
symbol: 'circle',
|
||||
showSymbol: false,
|
||||
smooth: true,
|
||||
encode: {
|
||||
x: 'time',
|
||||
y: item,
|
||||
tooltip: [
|
||||
item,
|
||||
],
|
||||
},
|
||||
data: data.map(i => {
|
||||
const seriesType = item as keyof ITakeMetric;
|
||||
return i[seriesType] !== null ? Number(i[seriesType]) : null;
|
||||
}),
|
||||
}));
|
||||
|
||||
const filterSeries = getFilterSeries(series);
|
||||
return {
|
||||
...baseLineConfig,
|
||||
tooltip: {
|
||||
...baseLineConfig.tooltip,
|
||||
formatter: (params: any) => {
|
||||
let result = params[0].value.time + '<br>';
|
||||
params.forEach((item: any) => {
|
||||
series.forEach((ele: any) => {
|
||||
if (ele.name === item.seriesName) {
|
||||
// tslint:disable-next-line:max-line-length
|
||||
result += '<span style="display:inline-block;margin-right:0px;border-radius:10px;width:9px;height:9px;background-color:' + item.color + '"></span>';
|
||||
return result += item.seriesName + ': ' + (item.data[item.seriesName].toFixed(2) || '') + '<br>';
|
||||
}
|
||||
});
|
||||
});
|
||||
return result;
|
||||
},
|
||||
},
|
||||
xAxis: {
|
||||
type: 'time',
|
||||
splitLine: false,
|
||||
},
|
||||
legend: {
|
||||
...baseLineConfig.legend,
|
||||
data: legend,
|
||||
},
|
||||
yAxis: {
|
||||
...baseLineConfig.yAxis,
|
||||
name: 'ms',
|
||||
},
|
||||
dataset: {
|
||||
source: data,
|
||||
},
|
||||
series: filterSeries,
|
||||
};
|
||||
};
|
||||
37
kafka-manager-console/src/lib/local-storage.ts
Normal file
37
kafka-manager-console/src/lib/local-storage.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
interface IData {
|
||||
startTime: number;
|
||||
value: string;
|
||||
time: number;
|
||||
}
|
||||
|
||||
export const setValueToLocalStorage = (key: string , value: string, time: number = 1 * 60 * 60 * 1000) => {
|
||||
const data = {
|
||||
startTime: (new Date()).getTime(),
|
||||
value,
|
||||
time,
|
||||
} as IData;
|
||||
localStorage.setItem(key, JSON.stringify(data));
|
||||
};
|
||||
|
||||
export const getValueFromLocalStorage = (key: string) => {
|
||||
let result = null;
|
||||
const data = localStorage.getItem(key);
|
||||
if (data) {
|
||||
try {
|
||||
result = JSON.parse(data);
|
||||
const { startTime, value, time } = result;
|
||||
const isTimeout = (new Date()).getTime() - startTime >= time;
|
||||
if (isTimeout) {
|
||||
deleteValueFromLocalStorage(key);
|
||||
}
|
||||
result = isTimeout ? null : value;
|
||||
} catch (err) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
export const deleteValueFromLocalStorage = (key: string) => {
|
||||
localStorage.removeItem(key);
|
||||
};
|
||||
25
kafka-manager-console/src/lib/url-parser.ts
Normal file
25
kafka-manager-console/src/lib/url-parser.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
interface IMap {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
export default () => {
|
||||
const Url = {
|
||||
hash: {} as IMap,
|
||||
search: {} as IMap,
|
||||
} as {
|
||||
hash: IMap;
|
||||
search: IMap;
|
||||
[key: string]: IMap;
|
||||
};
|
||||
|
||||
window.location.hash.slice(1).split('&').map(str => {
|
||||
const kv = str.split('=');
|
||||
Url.hash[kv[0]] = kv[1];
|
||||
});
|
||||
|
||||
window.location.search.slice(1).split('&').map(str => {
|
||||
const kv = str.split('=');
|
||||
Url.search[kv[0]] = kv[1];
|
||||
});
|
||||
return Url;
|
||||
};
|
||||
199
kafka-manager-console/src/lib/utils.ts
Normal file
199
kafka-manager-console/src/lib/utils.ts
Normal file
@@ -0,0 +1,199 @@
|
||||
import { IFilter, IStatusMap } from 'types/base-type';
|
||||
import { urlPrefix } from 'constants/left-menu';
|
||||
import { message } from 'antd';
|
||||
import moment, { Moment } from 'moment';
|
||||
import * as SparkMD5 from 'spark-md5';
|
||||
|
||||
export interface IMap {
|
||||
[index: string]: string;
|
||||
}
|
||||
interface ICookie {
|
||||
key: string;
|
||||
value?: string;
|
||||
time?: number;
|
||||
}
|
||||
export const getCookie = (key: string): string => {
|
||||
const map: IMap = {};
|
||||
document.cookie.split(';').map((kv) => {
|
||||
const d = kv.trim().split('=');
|
||||
map[d[0]] = d[1];
|
||||
return null;
|
||||
});
|
||||
return map[key];
|
||||
};
|
||||
|
||||
export const uuid = (): string => {
|
||||
return 'c' + `${Math.random()}`.slice(2);
|
||||
};
|
||||
|
||||
export const getRandomPassword = (len?: number) => {
|
||||
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
if (len) {
|
||||
let res = '';
|
||||
for (let i = 0; i < len; i++) {
|
||||
const id = Math.ceil(Math.random() * 62);
|
||||
res += chars[id];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
return Math.ceil(Math.random() * 100000);
|
||||
};
|
||||
|
||||
export const setCookie = (cData: ICookie[]) => {
|
||||
const date = new Date();
|
||||
cData.forEach(ele => {
|
||||
date.setTime(date.getTime() + (ele.time * 24 * 60 * 60 * 1000));
|
||||
const expires = 'expires=' + date.toUTCString();
|
||||
document.cookie = ele.key + '=' + ele.value + '; ' + expires + '; path=/';
|
||||
});
|
||||
};
|
||||
|
||||
export const deleteCookie = (cData: string[]) => {
|
||||
setCookie(cData.map(i => ({ key: i, value: '', time: -1 })));
|
||||
};
|
||||
|
||||
export const handleTabKey = (key: string) => {
|
||||
location.hash = key;
|
||||
};
|
||||
|
||||
export const tableFilter = <T>(data: T[], name: keyof T, nameMap: IStatusMap = null): IFilter[] => {
|
||||
if (!data) return [];
|
||||
const obj: any = {};
|
||||
return data.reduce((cur, pre) => {
|
||||
|
||||
if (!obj[pre[name]]) {
|
||||
obj[pre[name]] = true;
|
||||
cur.push({
|
||||
text: pre[name] !== undefined && nameMap ? nameMap[(pre[name] as any)] : pre[name],
|
||||
value: pre[name],
|
||||
});
|
||||
}
|
||||
return cur;
|
||||
}, []);
|
||||
};
|
||||
|
||||
export const handleTableData = (data: any[]) => {
|
||||
return data = data.map((item, index) => {
|
||||
item.key = index;
|
||||
return item;
|
||||
});
|
||||
};
|
||||
|
||||
export const computeChecksumMd5 = (file: File) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const chunkSize = 2097152; // Read in chunks of 2MB
|
||||
const spark = new SparkMD5.ArrayBuffer();
|
||||
const fileReader = new FileReader();
|
||||
|
||||
let cursor = 0; // current cursor in file
|
||||
|
||||
fileReader.onerror = () => {
|
||||
reject('MD5 computation failed - error reading the file');
|
||||
};
|
||||
|
||||
function processChunk(chunkStart: number) {
|
||||
const chunkEnd = Math.min(file.size, chunkStart + chunkSize);
|
||||
fileReader.readAsArrayBuffer(file.slice(chunkStart, chunkEnd));
|
||||
}
|
||||
|
||||
fileReader.onload = (e: any) => {
|
||||
spark.append(e.target.result); // Accumulate chunk to md5 computation
|
||||
cursor += chunkSize; // Move past this chunk
|
||||
|
||||
if (cursor < file.size) {
|
||||
processChunk(cursor);
|
||||
} else {
|
||||
// Computation ended, last chunk has been processed. Return as Promise value.
|
||||
// This returns the base64 encoded md5 hash, which is what
|
||||
// Rails ActiveStorage or cloud services expect
|
||||
// resolve(btoa(spark.end(true)));
|
||||
|
||||
// If you prefer the hexdigest form (looking like
|
||||
// '7cf530335b8547945f1a48880bc421b2'), replace the above line with:
|
||||
// resolve(spark.end());
|
||||
resolve(spark.end());
|
||||
}
|
||||
};
|
||||
|
||||
processChunk(0);
|
||||
});
|
||||
};
|
||||
|
||||
export const copyString = (url: any) => {
|
||||
const input = document.createElement('textarea');
|
||||
input.value = url;
|
||||
document.body.appendChild(input);
|
||||
input.select();
|
||||
if (document.execCommand('copy')) {
|
||||
message.success('复制成功');
|
||||
}
|
||||
input.remove();
|
||||
};
|
||||
|
||||
export const onHandleBack = () => {
|
||||
window.history.back();
|
||||
};
|
||||
|
||||
export const handlePageBack = (url: string) => {
|
||||
window.location.href = `${urlPrefix}${decodeURIComponent(url)}`;
|
||||
};
|
||||
|
||||
export const transMBToB = (value: number) => {
|
||||
const val = (value && value * 1024 * 1024) || '';
|
||||
return Number(val);
|
||||
};
|
||||
|
||||
export const transBToMB = (value: number) => {
|
||||
if (value === null) return '';
|
||||
|
||||
const val = Number.isInteger(value / 1024 / 1024) ? value / 1024 / 1024 : (value / 1024 / 1024).toFixed(2);
|
||||
return Number(val);
|
||||
};
|
||||
|
||||
export const transHourToMSecond = (value: number) => {
|
||||
const time = (value && value * 1000 * 60 * 60) || '';
|
||||
return Number(time);
|
||||
};
|
||||
|
||||
export const transMSecondToHour = (value: number) => {
|
||||
if (value === null) return '';
|
||||
|
||||
const time = Number.isInteger(value / 1000 / 60 / 60) ? value / 1000 / 60 / 60 : (value / 1000 / 60 / 60).toFixed(2);
|
||||
return Number(time);
|
||||
};
|
||||
|
||||
export const IsNotNaN = (value: any) => {
|
||||
return typeof value === 'number' && !isNaN(value);
|
||||
};
|
||||
|
||||
export const disabledDate = (current: Moment) => {
|
||||
// Can not select days after today
|
||||
return current && current >= moment().endOf('day');
|
||||
};
|
||||
|
||||
export const range = (start: any, end: any) => {
|
||||
const result = [];
|
||||
for (let i = start; i <= end; i++) {
|
||||
result.push(i);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
export const disabledDateTime = (dates: any) => {
|
||||
const hours = moment().hours(); // 0~23
|
||||
const minutes = moment().minutes(); // 0~59
|
||||
const seconds = moment().seconds(); // 0~59
|
||||
// 当日只能选择当前时间之后的时间点
|
||||
if (dates && moment(dates).date() === moment().date()) {
|
||||
return {
|
||||
disabledHours: () => range(hours + 1, 23),
|
||||
disabledMinutes: () => range(minutes + 1, 59),
|
||||
disabledSeconds: () => range(null, null),
|
||||
};
|
||||
}
|
||||
return {
|
||||
disabledHours: () => range(null, null),
|
||||
disabledMinutes: () => range(null, null),
|
||||
disabledSeconds: () => range(null, null),
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user