diff --git a/package.json b/package.json
index 9aaaf43..6222de5 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@kne-components/components-admin",
- "version": "1.1.47",
+ "version": "1.1.48",
"description": "用于实现一个后台管理系统的必要组件",
"scripts": {
"init": "husky",
diff --git a/src/components/Apis/getApis.js b/src/components/Apis/getApis.js
index 076f7cb..dc5e603 100644
--- a/src/components/Apis/getApis.js
+++ b/src/components/Apis/getApis.js
@@ -166,7 +166,7 @@ const getApis = options => {
statistics: {
/**
* 历史统计看板(GET)。
- * Query:`range`(7d|1m|1y)、`timezone`(IANA,与「今日」划界一致)。
+ * Query:`range`(7d|1m|3m|1y)、`timezone`(IANA,与「今日」划界一致)。
* 响应字段约定见 `src/components/Task/doc/api.md`「任务统计 HTTP」。
*/
getOverview: {
diff --git a/src/components/MessageManger/Dashboard/HistorySection.js b/src/components/MessageManger/Dashboard/HistorySection.js
index 3698f57..84a2b2a 100644
--- a/src/components/MessageManger/Dashboard/HistorySection.js
+++ b/src/components/MessageManger/Dashboard/HistorySection.js
@@ -26,10 +26,47 @@ import SectionHeader from './SectionHeader';
import { getClientIanaTimezone } from '../utils';
import style from './dashboard.module.scss';
-const RANGE_DAY_COUNT = { '7d': 7, '1m': 30, '1y': 365 };
+const RANGE_DAY_COUNT = { '7d': 7, '1m': 30, '3m': 90, '1y': 365 };
+const RANGE_AXIS_UNIT = { '7d': 'day', '1m': 'month', '3m': 'month', '1y': 'year' };
+const RANGE_MONTH_COUNT = { '1m': 1, '3m': 3 };
+
+const getAxisUnit = rangeKey => RANGE_AXIS_UNIT[rangeKey] || 'day';
+
+const formatAxisKey = (date, unit) => {
+ const value = String(date || '');
+ if (unit === 'year') return value.slice(0, 4);
+ if (unit === 'month') return value.slice(0, 7);
+ return value.slice(0, 10);
+};
+
+/** 本地日历上从 range 起点到今天的时间轴,随视图切换日/月/年粒度 */
+const buildLocalAxisForRange = rangeKey => {
+ const axisUnit = getAxisUnit(rangeKey);
+ if (axisUnit === 'year') {
+ const now = new Date();
+ const startYear = now.getFullYear() - 1;
+ return Array.from({ length: now.getFullYear() - startYear + 1 }, (_, i) => String(startYear + i));
+ }
+
+ if (axisUnit === 'month') {
+ const cursor = new Date();
+ cursor.setHours(0, 0, 0, 0);
+ cursor.setDate(1);
+ cursor.setMonth(cursor.getMonth() - (RANGE_MONTH_COUNT[rangeKey] || 1));
+ const end = new Date();
+ end.setHours(0, 0, 0, 0);
+ end.setDate(1);
+
+ const months = [];
+ while (cursor <= end) {
+ const y = cursor.getFullYear();
+ const m = String(cursor.getMonth() + 1).padStart(2, '0');
+ months.push(`${y}-${m}`);
+ cursor.setMonth(cursor.getMonth() + 1);
+ }
+ return months;
+ }
-/** 本地日历上从 range 起点到今天的日期轴(YYYY-MM-DD) */
-const buildLocalDateAxisForRange = rangeKey => {
const days = RANGE_DAY_COUNT[rangeKey] || 7;
const dates = [];
for (let i = days - 1; i >= 0; i -= 1) {
@@ -88,12 +125,17 @@ const HistorySection = createWithRemoteLoader({
const trendOption = (() => {
const recentTrend = data?.recentTrend || [];
const recentTrendByType = data?.recentTrendByType || [];
- const axisDates = recentTrend.length > 0 ? null : buildLocalDateAxisForRange(range);
+ const axisUnit = getAxisUnit(range);
+ const axisDates = recentTrend.length > 0 ? null : buildLocalAxisForRange(range);
const dateMap = {};
if (recentTrend.length > 0) {
recentTrend.forEach(item => {
- dateMap[item.date] = { date: item.date, total: item.count };
+ const date = formatAxisKey(item.date, axisUnit);
+ if (!dateMap[date]) {
+ dateMap[date] = { date, total: 0 };
+ }
+ dateMap[date].total += Number(item.count) || 0;
});
} else {
axisDates.forEach(d => {
@@ -101,11 +143,12 @@ const HistorySection = createWithRemoteLoader({
});
}
recentTrendByType.forEach(item => {
- if (!dateMap[item.date]) {
- dateMap[item.date] = { date: item.date, total: 0 };
+ const date = formatAxisKey(item.date, axisUnit);
+ if (!dateMap[date]) {
+ dateMap[date] = { date, total: 0 };
}
const key = item.type === 0 ? 'email' : 'sms';
- dateMap[item.date][key] = item.count;
+ dateMap[date][key] = (dateMap[date][key] || 0) + (Number(item.count) || 0);
});
const sorted = Object.values(dateMap).sort((a, b) => a.date.localeCompare(b.date));
diff --git a/src/components/MessageManger/Dashboard/constants.js b/src/components/MessageManger/Dashboard/constants.js
index 934e17c..6253856 100644
--- a/src/components/MessageManger/Dashboard/constants.js
+++ b/src/components/MessageManger/Dashboard/constants.js
@@ -1,4 +1,4 @@
-export const RANGE_OPTIONS = ['7d', '1m', '1y'];
+export const RANGE_OPTIONS = ['7d', '1m', '3m', '1y'];
export const buildUrlWithParams = (url, params = {}) => {
const query = Object.keys(params)
diff --git a/src/components/MessageManger/locale/en-US.js b/src/components/MessageManger/locale/en-US.js
index e38dffa..df149f4 100644
--- a/src/components/MessageManger/locale/en-US.js
+++ b/src/components/MessageManger/locale/en-US.js
@@ -54,6 +54,7 @@ const messages = {
TotalCount: 'Total Count',
Range_7d: 'Last 7 Days',
Range_1m: 'Last Month',
+ Range_3m: 'Last 3 Months',
Range_1y: 'Last Year',
Refresh: 'Refresh',
RealtimeConnected: 'Realtime Connected',
diff --git a/src/components/MessageManger/locale/zh-CN.js b/src/components/MessageManger/locale/zh-CN.js
index 1772921..309e2d4 100644
--- a/src/components/MessageManger/locale/zh-CN.js
+++ b/src/components/MessageManger/locale/zh-CN.js
@@ -54,6 +54,7 @@ const messages = {
TotalCount: '总数',
Range_7d: '近7天',
Range_1m: '近1个月',
+ Range_3m: '近3个月',
Range_1y: '近1年',
Refresh: '刷新',
RealtimeConnected: '实时已连接',
diff --git a/src/components/Task/Dashboard/HistorySection.js b/src/components/Task/Dashboard/HistorySection.js
index 2819e50..992fe0d 100644
--- a/src/components/Task/Dashboard/HistorySection.js
+++ b/src/components/Task/Dashboard/HistorySection.js
@@ -1,7 +1,7 @@
import { createWithRemoteLoader } from '@kne/remote-loader';
import Fetch from '@kne/react-fetch';
import { useState, useRef } from 'react';
-import { Button, Col, Row, Space, Segmented, Tag } from 'antd';
+import { Button, Col, Row, Select, Space, Segmented, Tag } from 'antd';
import { ReloadOutlined } from '@ant-design/icons';
import { Card as BoxCard } from '@kne/react-box';
import withLocale from '../withLocale';
@@ -16,7 +16,9 @@ import SectionHeader from './SectionHeader';
import { getClientIanaTimezone } from '../utils';
import style from './dashboard.module.scss';
-const RANGE_DAY_COUNT = { '7d': 7, '1m': 30, '1y': 365 };
+const RANGE_DAY_COUNT = { '7d': 7, '1m': 30, '3m': 90, '1y': 365 };
+const RANGE_AXIS_UNIT = { '7d': 'day', '1m': 'month', '3m': 'month', '1y': 'year' };
+const RANGE_MONTH_COUNT = { '1m': 1, '3m': 3 };
/** 每小时趋势「按状态」折线:避免 running 使用琥珀色易与其它图表橙色混淆 */
const HOURLY_STATUS_LINE_COLOR_MAP = {
@@ -24,8 +26,43 @@ const HOURLY_STATUS_LINE_COLOR_MAP = {
running: '#7c3aed'
};
-/** 本地日历上从 range 起点到今天的日期轴(YYYY-MM-DD) */
-const buildLocalDateAxisForRange = rangeKey => {
+const getAxisUnit = rangeKey => RANGE_AXIS_UNIT[rangeKey] || 'day';
+
+const formatAxisKey = (date, unit) => {
+ const value = String(date || '');
+ if (unit === 'year') return value.slice(0, 4);
+ if (unit === 'month') return value.slice(0, 7);
+ return value.slice(0, 10);
+};
+
+/** 本地日历上从 range 起点到今天的时间轴,随视图切换日/月/年粒度 */
+const buildLocalAxisForRange = rangeKey => {
+ const axisUnit = getAxisUnit(rangeKey);
+ if (axisUnit === 'year') {
+ const now = new Date();
+ const startYear = now.getFullYear() - 1;
+ return Array.from({ length: now.getFullYear() - startYear + 1 }, (_, i) => String(startYear + i));
+ }
+
+ if (axisUnit === 'month') {
+ const cursor = new Date();
+ cursor.setHours(0, 0, 0, 0);
+ cursor.setDate(1);
+ cursor.setMonth(cursor.getMonth() - (RANGE_MONTH_COUNT[rangeKey] || 1));
+ const end = new Date();
+ end.setHours(0, 0, 0, 0);
+ end.setDate(1);
+
+ const months = [];
+ while (cursor <= end) {
+ const y = cursor.getFullYear();
+ const m = String(cursor.getMonth() + 1).padStart(2, '0');
+ months.push(`${y}-${m}`);
+ cursor.setMonth(cursor.getMonth() + 1);
+ }
+ return months;
+ }
+
const days = RANGE_DAY_COUNT[rangeKey] || 7;
const dates = [];
for (let i = days - 1; i >= 0; i -= 1) {
@@ -40,6 +77,75 @@ const buildLocalDateAxisForRange = rangeKey => {
return dates;
};
+const buildRangeDateSet = rangeKey => {
+ const days = RANGE_DAY_COUNT[rangeKey] || 7;
+ const dates = [];
+ for (let i = days - 1; i >= 0; i -= 1) {
+ const d = new Date();
+ d.setHours(0, 0, 0, 0);
+ d.setDate(d.getDate() - i);
+ const y = d.getFullYear();
+ const m = String(d.getMonth() + 1).padStart(2, '0');
+ const day = String(d.getDate()).padStart(2, '0');
+ dates.push(`${y}-${m}-${day}`);
+ }
+ return new Set(dates);
+};
+
+const buildBucketedDurationRows = ({ rangeKey, durationTrend, runnerType, selectedTypes = [] }) => {
+ const axisKeys = durationTrend.length > 0 ? null : buildLocalAxisForRange(rangeKey);
+ const axisUnit = getAxisUnit(rangeKey);
+ const bucketMap = {};
+ const typeFilters = selectedTypes.map(String).filter(Boolean);
+
+ if (axisKeys) {
+ axisKeys.forEach(date => {
+ bucketMap[date] = { date, waitingSum: 0, executionSum: 0, weight: 0 };
+ });
+ }
+
+ durationTrend.forEach(item => {
+ const date = formatAxisKey(item.date, axisUnit);
+ if (!bucketMap[date]) bucketMap[date] = { date, waitingSum: 0, executionSum: 0, weight: 0 };
+
+ const byTypeForRunner = item?.byTypeByRunnerType?.[runnerType];
+ const durationItems = typeFilters.length > 0
+ ? typeFilters.map(type => byTypeForRunner?.[type]).filter(Boolean)
+ : [item?.byRunnerType?.[runnerType] || null].filter(Boolean);
+
+ durationItems.forEach(durationItem => {
+ const avgWaitingTime = Number(durationItem?.avgWaitingTime) || 0;
+ const avgExecutionTime = Number(durationItem?.avgExecutionTime) || 0;
+ const count = Number(durationItem?.count) || 0;
+ const weight = count > 0 ? count : avgWaitingTime > 0 || avgExecutionTime > 0 ? 1 : 0;
+
+ bucketMap[date].waitingSum += avgWaitingTime * weight;
+ bucketMap[date].executionSum += avgExecutionTime * weight;
+ bucketMap[date].weight += weight;
+ });
+ });
+
+ return Object.values(bucketMap)
+ .sort((a, b) => a.date.localeCompare(b.date))
+ .map(item => ({
+ date: item.date,
+ avgWaitingTime: item.weight > 0 ? item.waitingSum / item.weight : 0,
+ avgExecutionTime: item.weight > 0 ? item.executionSum / item.weight : 0
+ }));
+};
+
+const getDurationTaskTypesByRunner = (durationTrend, runnerType) => {
+ const typeSet = new Set();
+ durationTrend.forEach(item => {
+ Object.keys(item?.byTypeByRunnerType?.[runnerType] || {}).forEach(type => {
+ typeSet.add(String(type));
+ });
+ });
+ return Array.from(typeSet).sort((a, b) =>
+ a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' })
+ );
+};
+
const buildEmptyHorizontalBarOption = (placeholder, splitLineStyle, axisLineStyle, axisLabelStyle) => ({
tooltip: { show: false },
grid: { left: 6, right: 28, top: 10, bottom: 10, containLabel: true },
@@ -78,6 +184,8 @@ const HistorySection = createWithRemoteLoader({
const [range, setRange] = useState('7d');
/** 历史每小时趋势:按任务类型 | 按任务状态 */
const [hourlyHistoryDim, setHourlyHistoryDim] = useState('type');
+ const [manualDurationTypes, setManualDurationTypes] = useState([]);
+ const [systemDurationTypes, setSystemDurationTypes] = useState([]);
const reloadRef = useRef(() => {});
return (
@@ -115,12 +223,17 @@ const HistorySection = createWithRemoteLoader({
const trendOption = (() => {
const recentTrend = data?.recentTrend || [];
const recentTrendByType = data?.recentTrendByType || [];
- const axisDates = recentTrend.length > 0 ? null : buildLocalDateAxisForRange(range);
+ const axisUnit = getAxisUnit(range);
+ const axisDates = recentTrend.length > 0 ? null : buildLocalAxisForRange(range);
const dateMap = {};
if (recentTrend.length > 0) {
recentTrend.forEach(item => {
- dateMap[item.date] = { date: item.date, total: item.count };
+ const date = formatAxisKey(item.date, axisUnit);
+ if (!dateMap[date]) {
+ dateMap[date] = { date, total: 0 };
+ }
+ dateMap[date].total += Number(item.count) || 0;
});
} else {
axisDates.forEach(d => {
@@ -128,10 +241,11 @@ const HistorySection = createWithRemoteLoader({
});
}
recentTrendByType.forEach(item => {
- if (!dateMap[item.date]) {
- dateMap[item.date] = { date: item.date, total: 0 };
+ const date = formatAxisKey(item.date, axisUnit);
+ if (!dateMap[date]) {
+ dateMap[date] = { date, total: 0 };
}
- dateMap[item.date][item.type] = item.count;
+ dateMap[date][item.type] = (dateMap[date][item.type] || 0) + (Number(item.count) || 0);
});
const sorted = Object.values(dateMap).sort((a, b) => a.date.localeCompare(b.date));
@@ -251,6 +365,14 @@ const HistorySection = createWithRemoteLoader({
const typeTotal = typeEntries.reduce((sum, { count }) => sum + count, 0);
const durationTrend = data?.durationTrend || [];
+ const manualDurationTaskTypes = getDurationTaskTypesByRunner(durationTrend, 'manual');
+ const systemDurationTaskTypes = getDurationTaskTypesByRunner(durationTrend, 'system');
+ const effectiveManualDurationTypes = manualDurationTypes.filter(type =>
+ manualDurationTaskTypes.includes(String(type))
+ );
+ const effectiveSystemDurationTypes = systemDurationTypes.filter(type =>
+ systemDurationTaskTypes.includes(String(type))
+ );
const buildWaitExecDurationOption = rows => {
const dates = rows.map(item => item.date);
@@ -312,35 +434,18 @@ const HistorySection = createWithRemoteLoader({
};
};
- const durationAxisDates = buildLocalDateAxisForRange(range);
- const manualDurationRows = durationTrend.length
- ? durationTrend.map(day => {
- const b = day?.byRunnerType?.manual;
- return {
- date: day.date,
- avgWaitingTime: b?.avgWaitingTime ?? 0,
- avgExecutionTime: b?.avgExecutionTime ?? 0
- };
- })
- : durationAxisDates.map(date => ({
- date,
- avgWaitingTime: 0,
- avgExecutionTime: 0
- }));
- const systemDurationRows = durationTrend.length
- ? durationTrend.map(day => {
- const b = day?.byRunnerType?.system;
- return {
- date: day.date,
- avgWaitingTime: b?.avgWaitingTime ?? 0,
- avgExecutionTime: b?.avgExecutionTime ?? 0
- };
- })
- : durationAxisDates.map(date => ({
- date,
- avgWaitingTime: 0,
- avgExecutionTime: 0
- }));
+ const manualDurationRows = buildBucketedDurationRows({
+ rangeKey: range,
+ durationTrend,
+ runnerType: 'manual',
+ selectedTypes: effectiveManualDurationTypes
+ });
+ const systemDurationRows = buildBucketedDurationRows({
+ rangeKey: range,
+ durationTrend,
+ runnerType: 'system',
+ selectedTypes: effectiveSystemDurationTypes
+ });
const manualDurationOption = buildWaitExecDurationOption(manualDurationRows);
const systemDurationOption = buildWaitExecDurationOption(systemDurationRows);
@@ -524,24 +629,84 @@ const HistorySection = createWithRemoteLoader({
-
-
-
-
-
-
-
-
-
-
-
-
+
+ {taskTypeList => {
+ const typeLabelMap = {};
+ (taskTypeList || []).forEach(item => {
+ const value = String(item.value);
+ typeLabelMap[value] = item.label || item.description || value;
+ });
+ const buildTaskTypeOptions = types => types.map((type, i) => ({
+ value: type,
+ label: typeLabelMap[type] || type,
+ color: TASK_TYPE_COLOR_MAP[i % TASK_TYPE_COLOR_MAP.length]
+ }));
+ const manualTaskTypeOptions = buildTaskTypeOptions(manualDurationTaskTypes);
+ const systemTaskTypeOptions = buildTaskTypeOptions(systemDurationTaskTypes);
+ const renderTaskTypeSelect = (value, onChange, options) => {
+ const optionColorMap = options.reduce((result, option) => {
+ result[option.value] = option.color;
+ return result;
+ }, {});
+ return (
+
{taskTypeList => {
@@ -551,7 +716,7 @@ const HistorySection = createWithRemoteLoader({
});
const hourlyCompletionTrend = data?.hourlyCompletionTrend || [];
- const rangeDates = new Set(buildLocalDateAxisForRange(range));
+ const rangeDates = buildRangeDateSet(range);
const hourLabels = Array.from({ length: 24 }, (_, i) => `${String(i).padStart(2, '0')}:00`);
const empty24 = () => Array.from({ length: 24 }, () => 0);
@@ -749,7 +914,7 @@ const HistorySection = createWithRemoteLoader({
/>
}
>
-
+
);
}}
diff --git a/src/components/Task/Dashboard/constants.js b/src/components/Task/Dashboard/constants.js
index 9111e63..3597f31 100644
--- a/src/components/Task/Dashboard/constants.js
+++ b/src/components/Task/Dashboard/constants.js
@@ -1,6 +1,6 @@
import { defaultColors } from '@kne/react-box';
-export const RANGE_OPTIONS = ['7d', '1m', '1y'];
+export const RANGE_OPTIONS = ['7d', '1m', '3m', '1y'];
export const buildUrlWithParams = (url, params = {}) => {
const query = Object.keys(params)
diff --git a/src/components/Task/Dashboard/dashboard.module.scss b/src/components/Task/Dashboard/dashboard.module.scss
index 57b549a..e77b07e 100644
--- a/src/components/Task/Dashboard/dashboard.module.scss
+++ b/src/components/Task/Dashboard/dashboard.module.scss
@@ -361,6 +361,34 @@
margin-top: 0;
}
+.durationTaskTypeSelect {
+ border-radius: 8px;
+ background: #f8fafc;
+ transition: background 0.15s ease;
+
+ &:hover {
+ background: #f1f5f9;
+ }
+
+ :global(.ant-select-selector) {
+ padding-inline: 8px !important;
+ background: transparent !important;
+ }
+
+ :global(.ant-select-selection-placeholder) {
+ color: #64748b;
+ font-size: 12px;
+ }
+}
+
+.durationTaskTypeTag {
+ margin-inline-end: 4px;
+ border-radius: 10px;
+ font-size: 11px;
+ font-weight: 600;
+ line-height: 18px;
+}
+
/* 紧跟占比条后的第一张趋势图:纵向更紧凑 */
.historyTrendTightTop {
margin-top: 10px;
diff --git a/src/components/Task/README.md b/src/components/Task/README.md
index 602fa37..b81043e 100644
--- a/src/components/Task/README.md
+++ b/src/components/Task/README.md
@@ -645,7 +645,7 @@ render();
| 参数 | 说明 |
| --- | --- |
-| `range` | 历史区间:`7d` \| `1m` \| `1y` |
+| `range` | 历史区间:`7d` \| `1m` \| `3m` \| `1y` |
| `timezone` | 浏览器 IANA 时区(如 `Asia/Shanghai`),与后端按日历日聚合的划界一致 |
**响应**(节选,以实际后端为准)
diff --git a/src/components/Task/doc/api.md b/src/components/Task/doc/api.md
index e4f30c4..316e49d 100644
--- a/src/components/Task/doc/api.md
+++ b/src/components/Task/doc/api.md
@@ -88,7 +88,7 @@
| 参数 | 说明 |
| --- | --- |
-| `range` | 历史区间:`7d` \| `1m` \| `1y` |
+| `range` | 历史区间:`7d` \| `1m` \| `3m` \| `1y` |
| `timezone` | 浏览器 IANA 时区(如 `Asia/Shanghai`),与后端按日历日聚合的划界一致 |
**响应**(节选,以实际后端为准)
diff --git a/src/components/Task/locale/en-US.js b/src/components/Task/locale/en-US.js
index 5e2aec8..8563166 100644
--- a/src/components/Task/locale/en-US.js
+++ b/src/components/Task/locale/en-US.js
@@ -93,6 +93,7 @@ const locale = {
TotalTasks: 'Total Tasks',
Range_7d: 'Last 7 Days',
Range_1m: 'Last Month',
+ Range_3m: 'Last 3 Months',
Range_1y: 'Last Year',
Refresh: 'Refresh',
Dawn: 'Dawn',
@@ -104,6 +105,7 @@ const locale = {
HistoricalHourlyTrendTitle: 'Hourly trend',
HourlyTrendModeByType: 'By task type',
HourlyTrendModeByStatus: 'By task status',
+ TaskTypeFilterPlaceholder: 'All',
StatusDistribution: 'Status Distribution',
TaskTypeDistribution: 'Task Type Distribution'
};
diff --git a/src/components/Task/locale/zh-CN.js b/src/components/Task/locale/zh-CN.js
index 920482a..e6bcce9 100644
--- a/src/components/Task/locale/zh-CN.js
+++ b/src/components/Task/locale/zh-CN.js
@@ -93,6 +93,7 @@ const locale = {
TotalTasks: '任务总数',
Range_7d: '近7天',
Range_1m: '近1个月',
+ Range_3m: '近3个月',
Range_1y: '近1年',
Refresh: '刷新',
Dawn: '凌晨',
@@ -104,6 +105,7 @@ const locale = {
HistoricalHourlyTrendTitle: '每小时趋势',
HourlyTrendModeByType: '按任务类型',
HourlyTrendModeByStatus: '按任务状态',
+ TaskTypeFilterPlaceholder: '全部',
StatusDistribution: '任务状态分布',
TaskTypeDistribution: '任务类型分布'
};
diff --git a/src/mockPreset/index.js b/src/mockPreset/index.js
index 5c3691c..1098e7d 100644
--- a/src/mockPreset/index.js
+++ b/src/mockPreset/index.js
@@ -119,7 +119,7 @@ const apis = merge({}, getApis(), {
loader: ({ params }) => {
const range = params?.range || '7d';
const now = new Date();
- const days = range === '1y' ? 365 : range === '1m' ? 30 : 7;
+ const days = range === '1y' ? 365 : range === '3m' ? 90 : range === '1m' ? 30 : 7;
const recentTrend = [];
const recentTrendByStatus = [];
const recentTrendByType = [];
@@ -159,6 +159,16 @@ const apis = merge({}, getApis(), {
byRunnerType: {
manual: { count: Math.floor(total * 0.4), avgWaitingTime: Math.floor(Math.random() * 2000) + 500, avgExecutionTime: Math.floor(Math.random() * 6000) + 2000, avgTotalTime: Math.floor(Math.random() * 8000) + 3000 },
system: { count: Math.ceil(total * 0.6), avgWaitingTime: Math.floor(Math.random() * 2000) + 500, avgExecutionTime: Math.floor(Math.random() * 6000) + 2000, avgTotalTime: Math.floor(Math.random() * 8000) + 3000 }
+ },
+ byTypeByRunnerType: {
+ manual: {
+ export: { count: Math.floor(total * 0.25), avgWaitingTime: Math.floor(Math.random() * 2000) + 500, avgExecutionTime: Math.floor(Math.random() * 6000) + 2000, avgTotalTime: Math.floor(Math.random() * 8000) + 3000 },
+ import: { count: Math.ceil(total * 0.15), avgWaitingTime: Math.floor(Math.random() * 2000) + 500, avgExecutionTime: Math.floor(Math.random() * 6000) + 2000, avgTotalTime: Math.floor(Math.random() * 8000) + 3000 }
+ },
+ system: {
+ export: { count: Math.floor(total * 0.35), avgWaitingTime: Math.floor(Math.random() * 2000) + 500, avgExecutionTime: Math.floor(Math.random() * 6000) + 2000, avgTotalTime: Math.floor(Math.random() * 8000) + 3000 },
+ import: { count: Math.ceil(total * 0.25), avgWaitingTime: Math.floor(Math.random() * 2000) + 500, avgExecutionTime: Math.floor(Math.random() * 6000) + 2000, avgTotalTime: Math.floor(Math.random() * 8000) + 3000 }
+ }
}
});
['import', 'export'].forEach(type => {
@@ -186,7 +196,7 @@ const apis = merge({}, getApis(), {
const totalWaiting = recentTrendByStatus.filter(item => item.status === 'waiting').reduce((sum, item) => sum + item.count, 0);
return {
range,
- rangeLabel: range === '7d' ? '近7天' : range === '1m' ? '近1个月' : '近1年',
+ rangeLabel: range === '7d' ? '近7天' : range === '1m' ? '近1个月' : range === '3m' ? '近3个月' : '近1年',
totalTasks: totalSuccess + totalFailed + totalRunning + totalPending + totalCanceled + totalWaiting,
byStatus: { success: totalSuccess, failed: totalFailed, running: totalRunning, pending: totalPending, canceled: totalCanceled, waiting: totalWaiting },
byType: { export: Math.floor((totalSuccess + totalFailed) * 0.6), import: Math.ceil((totalSuccess + totalFailed) * 0.4) },
@@ -849,7 +859,7 @@ const apis = merge({}, getApis(), {
loader: ({ params }) => {
const range = params?.range || '7d';
const now = new Date();
- const days = range === '1y' ? 365 : range === '1m' ? 30 : 7;
+ const days = range === '1y' ? 365 : range === '3m' ? 90 : range === '1m' ? 30 : 7;
const recentTrend = [];
const recentTrendByType = [];
for (let i = days - 1; i >= 0; i--) {
@@ -867,7 +877,7 @@ const apis = merge({}, getApis(), {
const smsTotal = recentTrendByType.filter(item => item.type === 1).reduce((sum, item) => sum + item.count, 0);
return {
range,
- rangeLabel: range === '7d' ? '近7天' : range === '1m' ? '近1个月' : '近1年',
+ rangeLabel: range === '7d' ? '近7天' : range === '1m' ? '近1个月' : range === '3m' ? '近3个月' : '近1年',
totalRecords,
byType: { '0': emailTotal, '1': smsTotal },
byCode: { welcome: Math.floor(totalRecords * 0.4), verify: Math.floor(totalRecords * 0.3), notification: Math.floor(totalRecords * 0.2), alert: totalRecords - Math.floor(totalRecords * 0.4) - Math.floor(totalRecords * 0.3) - Math.floor(totalRecords * 0.2) },
diff --git a/src/preset.js b/src/preset.js
index 5dad17c..ffe0cfd 100644
--- a/src/preset.js
+++ b/src/preset.js
@@ -55,7 +55,7 @@ export const globalInit = async () => {
const componentsCoreRemote = {
...registry,
remote: 'components-core',
- defaultVersion: '0.4.73'
+ defaultVersion: '0.5.0'
};
remoteLoaderPreset({
remotes: {
@@ -71,7 +71,7 @@ export const globalInit = async () => {
//url: 'http://localhost:3010',
//tpl: '{{url}}',
remote: 'components-thirdparty',
- defaultVersion: '0.1.17'
+ defaultVersion: '0.1.24'
},
'components-admin':
process.env.NODE_ENV === 'development'