feat(rain): add date preset picker and reduce time clarification prompts.
Memind CI / Test, build, and release guards (push) Successful in 5m5s
Memind CI / Test, build, and release guards (push) Successful in 5m5s
Default to last 3 days in UI and backend, only ask when time is truly ambiguous, and treat「做成页面」as HTML report pages without follow-up questions. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+2
-2
@@ -550,8 +550,8 @@ export function buildChatSkillPrompt(promptKey, skillName) {
|
||||
);
|
||||
case 'rain':
|
||||
return (
|
||||
'【Rain · MeInput 输入分析】请描述要分析的时间区间和你的诉求(例如「总结昨天我在做什么」)。' +
|
||||
'未写时间则默认近3天;区间不明确时我会先追问。我的问题是:'
|
||||
'【Rain · MeInput 输入分析】在下方选择时间范围(默认近3天),描述你的诉求(例如「总结输入活动」或「做成页面报告」)。' +
|
||||
'我的问题是:'
|
||||
);
|
||||
case 'summarize':
|
||||
return '请总结以下内容,提炼核心结论、重点信息和可执行建议(条理清晰、中文输出):';
|
||||
|
||||
+20
-4
@@ -1,6 +1,6 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { resolveRainTimeRange, RAIN_DEFAULT_DAYS } from './rain-service/time-range.mjs';
|
||||
import { resolveRainTimeRange, RAIN_DEFAULT_DAYS, resolveRainTimeRangeFromPreset } from './rain-service/time-range.mjs';
|
||||
import { formatMeinputFullBlock } from './rain-service/meinput-full.mjs';
|
||||
import { buildRainGooseHandoffText, stripRainSkillPrefix } from './rain-service/llm-analysis.mjs';
|
||||
import {
|
||||
@@ -22,12 +22,28 @@ test('resolveRainTimeRange defaults to 3 days when no time hint', () => {
|
||||
assert.ok(spanMs >= RAIN_DEFAULT_DAYS * 24 * 60 * 60 * 1000 - 60_000);
|
||||
});
|
||||
|
||||
test('resolveRainTimeRange asks clarification for ambiguous phrases', () => {
|
||||
const result = resolveRainTimeRange('前几天我在做什么', new Date('2026-09-04T12:00:00+08:00'));
|
||||
test('resolveRainTimeRange defaults to 3 days for fuzzy phrases like 前几天', () => {
|
||||
const now = new Date('2026-09-04T12:00:00+08:00');
|
||||
const result = resolveRainTimeRange('前几天我在做什么', now);
|
||||
assert.equal(result.needsClarification, false);
|
||||
assert.equal(result.source, 'default_3d');
|
||||
});
|
||||
|
||||
test('resolveRainTimeRange asks clarification only for strictly ambiguous phrases', () => {
|
||||
const result = resolveRainTimeRange('不太确定那段时间我在做什么', new Date('2026-09-04T12:00:00+08:00'));
|
||||
assert.equal(result.needsClarification, true);
|
||||
assert.match(result.clarificationQuestion ?? '', /起止时间/);
|
||||
});
|
||||
|
||||
test('resolveRainTimeRangeFromPreset resolves UI presets', () => {
|
||||
const now = new Date('2026-09-06T12:00:00+08:00');
|
||||
const today = resolveRainTimeRangeFromPreset('today', now);
|
||||
assert.equal(today.label, '今天');
|
||||
assert.ok(today.range?.start);
|
||||
const threeDays = resolveRainTimeRangeFromPreset('3d', now);
|
||||
assert.equal(threeDays.label, '近3天');
|
||||
});
|
||||
|
||||
test('resolveRainTimeRange parses yesterday explicitly', () => {
|
||||
const now = new Date('2026-09-04T12:00:00+08:00');
|
||||
const result = resolveRainTimeRange('我昨天输入了什么', now);
|
||||
@@ -94,6 +110,6 @@ test('filterChatSkills hides page templates by default', () => {
|
||||
});
|
||||
|
||||
test('stripRainSkillPrefix removes rain prompt header', () => {
|
||||
const text = stripRainSkillPrefix('【Rain · MeInput 输入分析】请描述要分析的时间区间和你的诉求。未写时间则默认近3天;区间不明确时我会先追问。我的问题是:总结输入');
|
||||
const text = stripRainSkillPrefix('【Rain · MeInput 输入分析】在下方选择时间范围(默认近3天),描述你的诉求(例如「总结输入活动」或「做成页面报告」)。我的问题是:总结输入');
|
||||
assert.equal(text, '总结输入');
|
||||
});
|
||||
|
||||
+10
-3
@@ -1,10 +1,10 @@
|
||||
import { RAIN_SKILL_NAME, isRainModeMessage } from '../chat-skills.mjs';
|
||||
import { loadRainMeinputRecords, formatMeinputFullBlock } from './meinput-full.mjs';
|
||||
import { runRainLlmAnalysis, buildRainGooseHandoffText, stripRainSkillPrefix } from './llm-analysis.mjs';
|
||||
import { resolveRainTimeRange, formatRainTimeRangeLabel } from './time-range.mjs';
|
||||
import { resolveRainTimeRange, formatRainTimeRangeLabel, resolveRainTimeRangeFromPreset, RAIN_TIME_PRESET_IDS } from './time-range.mjs';
|
||||
|
||||
export { RAIN_SKILL_NAME, isRainModeMessage };
|
||||
export { resolveRainTimeRange, formatRainTimeRangeLabel, RAIN_DEFAULT_DAYS } from './time-range.mjs';
|
||||
export { resolveRainTimeRange, formatRainTimeRangeLabel, RAIN_DEFAULT_DAYS, resolveRainTimeRangeFromPreset, RAIN_TIME_PRESET_IDS } from './time-range.mjs';
|
||||
export { formatMeinputFullBlock, loadRainMeinputRecords } from './meinput-full.mjs';
|
||||
export { runRainLlmAnalysis, buildRainGooseHandoffText, stripRainSkillPrefix } from './llm-analysis.mjs';
|
||||
|
||||
@@ -31,7 +31,14 @@ export async function executeRainPipeline(input) {
|
||||
: String(input.userMessage?.content ?? ''),
|
||||
);
|
||||
|
||||
const timeResolution = resolveRainTimeRange(displayText);
|
||||
const preset = String(input.userMessage?.metadata?.memindRun?.rainTimePreset ?? '').trim();
|
||||
const timeResolution = RAIN_TIME_PRESET_IDS.includes(preset)
|
||||
? {
|
||||
needsClarification: false,
|
||||
clarificationQuestion: null,
|
||||
...resolveRainTimeRangeFromPreset(preset),
|
||||
}
|
||||
: resolveRainTimeRange(displayText);
|
||||
if (timeResolution.needsClarification) {
|
||||
return {
|
||||
phase: 'clarify',
|
||||
|
||||
@@ -2,7 +2,7 @@ function stripRainSkillPrefix(text) {
|
||||
let next = String(text ?? '').trim();
|
||||
next = next.replace(/^【Rain[^】]*】\s*/u, '');
|
||||
next = next.replace(/^请使用\s+rain\s+技能[::]\s*/iu, '');
|
||||
if (/^请描述要分析的时间区间/u.test(next)) {
|
||||
if (/^请描述要分析的时间/u.test(next) || /^在下方选择时间范围/u.test(next)) {
|
||||
const marker = '我的问题是:';
|
||||
const idx = next.indexOf(marker);
|
||||
if (idx >= 0) next = next.slice(idx + marker.length);
|
||||
@@ -32,6 +32,9 @@ export async function runRainLlmAnalysis(input) {
|
||||
'{"needs_clarification":boolean,"clarification_question":string|null,"user_goal":string,"meinput_analysis":string,"suggested_next_steps":string[],"user_reply":string}',
|
||||
'- needs_clarification=true 时:clarification_question 必填,user_reply 用自然语言向用户追问;meinput_analysis 可为空。',
|
||||
'- needs_clarification=false 时:meinput_analysis 按时间线归纳用户在各 App 的输入活动;user_reply 是可直接展示给用户的中文回复(含区间说明);suggested_next_steps 供下游 Agent 参考(如生成报告页、继续追问)。',
|
||||
'- 时间区间已在输入中给定,禁止追问「这几天指哪几天」或让用户再次确认区间;若查询范围内实际有记录的时段更短,在 user_reply 中说明实际覆盖时段即可。',
|
||||
'- 用户提到「做成页面」「生成报告」时,默认理解为 MindSpace HTML 可视化报告页;suggested_next_steps 应包含生成 HTML 报告页,禁止追问是要卡片还是页面。',
|
||||
'- needs_clarification 仅用于用户诉求本身完全无法理解(与时间区间、页面形式无关)。',
|
||||
'- 不要把内部排序分数、source 字段名暴露给用户。',
|
||||
].join('\n');
|
||||
|
||||
@@ -99,6 +102,7 @@ export function buildRainGooseHandoffText({
|
||||
return [
|
||||
'[Rain · MeInput 分析简报]',
|
||||
'以下简报由 Rain 分析层基于 MeInput 全量原始输入生成。请据此决定如何回复用户、是否调用工具或 skill;不要重复询问时间区间。',
|
||||
'若用户诉求含「做成页面」或「生成报告」,直接生成 MindSpace HTML 可视化报告页,勿再追问形式。',
|
||||
'',
|
||||
`时间区间:${timeRangeLabel}`,
|
||||
`原始记录条数:${recordCount}`,
|
||||
|
||||
+61
-14
@@ -20,6 +20,15 @@ function addDays(anchor, deltaDays) {
|
||||
return new Date(ms);
|
||||
}
|
||||
|
||||
/** @param {Date} anchor */
|
||||
function startOfDay(anchor) {
|
||||
const p = new Date(anchor.getTime() + TZ_OFFSET_MIN * 60_000);
|
||||
const ms =
|
||||
Date.UTC(p.getUTCFullYear(), p.getUTCMonth(), p.getUTCDate(), 0, 0, 0, 0) -
|
||||
TZ_OFFSET_MIN * 60_000;
|
||||
return new Date(ms);
|
||||
}
|
||||
|
||||
/** @param {Date} anchor */
|
||||
function endOfDay(anchor) {
|
||||
const p = new Date(anchor.getTime() + TZ_OFFSET_MIN * 60_000);
|
||||
@@ -29,13 +38,55 @@ function endOfDay(anchor) {
|
||||
return new Date(ms);
|
||||
}
|
||||
|
||||
const AMBIGUOUS_TIME_PATTERNS = [
|
||||
/前几天/u,
|
||||
/那段(?:时间|日子)/u,
|
||||
/上次(?:那)?(?:段|个)/u,
|
||||
/大概.{0,6}(?:昨天|前天|上周|几)/u,
|
||||
/左右/u,
|
||||
/** @param {Date} now */
|
||||
function buildDefault3dRange(now) {
|
||||
return {
|
||||
start: addDays(now, -RAIN_DEFAULT_DAYS).toISOString(),
|
||||
end: endOfDay(now).toISOString(),
|
||||
};
|
||||
}
|
||||
|
||||
export const RAIN_TIME_PRESET_IDS = ['today', 'yesterday', '3d', '7d'];
|
||||
|
||||
/**
|
||||
* @param {string} presetId
|
||||
* @param {Date} [now]
|
||||
*/
|
||||
export function resolveRainTimeRangeFromPreset(presetId, now = new Date()) {
|
||||
const id = String(presetId ?? '3d').trim();
|
||||
if (id === 'today') {
|
||||
return {
|
||||
range: { start: startOfDay(now).toISOString(), end: endOfDay(now).toISOString() },
|
||||
source: 'ui_preset',
|
||||
label: '今天',
|
||||
};
|
||||
}
|
||||
if (id === 'yesterday') {
|
||||
const day = addDays(now, -1);
|
||||
return {
|
||||
range: { start: startOfDay(day).toISOString(), end: endOfDay(day).toISOString() },
|
||||
source: 'ui_preset',
|
||||
label: '昨天',
|
||||
};
|
||||
}
|
||||
if (id === '7d') {
|
||||
return {
|
||||
range: { start: addDays(now, -7).toISOString(), end: endOfDay(now).toISOString() },
|
||||
source: 'ui_preset',
|
||||
label: '近7天',
|
||||
};
|
||||
}
|
||||
return {
|
||||
range: buildDefault3dRange(now),
|
||||
source: 'ui_preset',
|
||||
label: `近${RAIN_DEFAULT_DAYS}天`,
|
||||
};
|
||||
}
|
||||
|
||||
/** Only truly unknowable time phrases trigger clarification; others fall back to default 3d. */
|
||||
const STRICT_AMBIGUOUS_TIME_PATTERNS = [
|
||||
/不太确定.{0,8}时间/u,
|
||||
/说不清.{0,6}(?:哪|什么).{0,4}(?:天|时间)/u,
|
||||
];
|
||||
|
||||
const EXPLICIT_TIME_HINT =
|
||||
@@ -48,7 +99,7 @@ const EXPLICIT_TIME_HINT =
|
||||
export function resolveRainTimeRange(query, now = new Date()) {
|
||||
const text = String(query ?? '').trim();
|
||||
|
||||
for (const pattern of AMBIGUOUS_TIME_PATTERNS) {
|
||||
for (const pattern of STRICT_AMBIGUOUS_TIME_PATTERNS) {
|
||||
if (pattern.test(text)) {
|
||||
return {
|
||||
needsClarification: true,
|
||||
@@ -62,11 +113,9 @@ export function resolveRainTimeRange(query, now = new Date()) {
|
||||
}
|
||||
|
||||
if (!EXPLICIT_TIME_HINT.test(text)) {
|
||||
const end = endOfDay(now);
|
||||
const start = addDays(now, -RAIN_DEFAULT_DAYS);
|
||||
return {
|
||||
needsClarification: false,
|
||||
range: { start: start.toISOString(), end: end.toISOString() },
|
||||
range: buildDefault3dRange(now),
|
||||
source: 'default_3d',
|
||||
label: `近${RAIN_DEFAULT_DAYS}天`,
|
||||
};
|
||||
@@ -77,12 +126,10 @@ export function resolveRainTimeRange(query, now = new Date()) {
|
||||
scope.rule_hits?.includes('time:default_week') ||
|
||||
scope.rule_hits?.includes('time:recent_fuzzy');
|
||||
|
||||
if (isDefaultFallback && /最近|近期|这几天/u.test(text) && !/最近\s*\d+\s*天/u.test(text)) {
|
||||
const end = endOfDay(now);
|
||||
const start = addDays(now, -RAIN_DEFAULT_DAYS);
|
||||
if (isDefaultFallback && /最近|近期|这几天|前几天|那段(?:时间|日子)/u.test(text) && !/最近\s*\d+\s*天/u.test(text)) {
|
||||
return {
|
||||
needsClarification: false,
|
||||
range: { start: start.toISOString(), end: end.toISOString() },
|
||||
range: buildDefault3dRange(now),
|
||||
source: 'default_3d',
|
||||
label: `近${RAIN_DEFAULT_DAYS}天`,
|
||||
};
|
||||
|
||||
@@ -33,6 +33,7 @@ import {
|
||||
import { AvatarPicker } from './AvatarPicker';
|
||||
import { ChatSkillPicker } from './ChatSkillPicker';
|
||||
import { ChatSkillIcon } from './ChatSkillIcons';
|
||||
import { RainTimeRangeBar } from './RainTimeRangeBar';
|
||||
import { PageTemplateShopModal } from './PageTemplateShopModal';
|
||||
import { ChatLoadingSpinner } from './ChatLoadingSpinner';
|
||||
import { ChatSharePreviewModal } from './ChatSharePreviewModal';
|
||||
@@ -42,6 +43,11 @@ import { PageSaveDialog } from './PageSaveDialog';
|
||||
import { VoiceInputButton } from './VoiceInputButton';
|
||||
import type { CapabilityMap, ChatFileAttachment, ChatState, Message, PortalUser, Session, ToolConfirmation } from '../types';
|
||||
import type { MindSpaceSaveCategory } from '../types';
|
||||
import {
|
||||
DEFAULT_RAIN_TIME_PRESET,
|
||||
RAIN_SKILL_ID,
|
||||
type RainTimePresetId,
|
||||
} from '../utils/rainTimeRange';
|
||||
|
||||
const CHAT_PLACEHOLDER_PROMPTS = [
|
||||
'帮我写一篇温柔一点的小短文',
|
||||
@@ -202,6 +208,7 @@ export function ChatPanel({
|
||||
pgRequired?: boolean;
|
||||
imageGenerationMode?: ImageGenerationMode;
|
||||
selectedChatSkill?: string;
|
||||
rainTimePreset?: RainTimePresetId;
|
||||
fileAttachments?: ChatFileAttachment[];
|
||||
},
|
||||
) => void | Promise<void>;
|
||||
@@ -241,6 +248,8 @@ export function ChatPanel({
|
||||
const [deepReasoningTipVisible, setDeepReasoningTipVisible] = useState(false);
|
||||
const [chatControlOnboardingStep, setChatControlOnboardingStep] = useState<0 | 1 | null>(null);
|
||||
const [templateShopOpen, setTemplateShopOpen] = useState(false);
|
||||
const [activeRainSkill, setActiveRainSkill] = useState(false);
|
||||
const [rainTimePreset, setRainTimePreset] = useState<RainTimePresetId>(DEFAULT_RAIN_TIME_PRESET);
|
||||
const [activeTemplatePrefill, setActiveTemplatePrefill] = useState<{
|
||||
skillId: string;
|
||||
label: string;
|
||||
@@ -840,8 +849,12 @@ export function ChatPanel({
|
||||
pgRequired: false,
|
||||
imageGenerationMode: 'auto',
|
||||
selectedChatSkill,
|
||||
...(selectedChatSkill === RAIN_SKILL_ID ? { rainTimePreset } : {}),
|
||||
fileAttachments: fileAttachmentsToSend,
|
||||
});
|
||||
if (selectedChatSkill === RAIN_SKILL_ID) {
|
||||
setActiveRainSkill(false);
|
||||
}
|
||||
uploadedImages.forEach(revokePendingImage);
|
||||
setPendingImages([]);
|
||||
setPendingFiles([]);
|
||||
@@ -868,6 +881,7 @@ export function ChatPanel({
|
||||
}, [
|
||||
activeTemplatePrefill,
|
||||
forceDeepReasoning,
|
||||
rainTimePreset,
|
||||
input,
|
||||
onSubmit,
|
||||
onUploadFile,
|
||||
@@ -1255,6 +1269,13 @@ export function ChatPanel({
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
{activeRainSkill && !taskInputStatusText && (
|
||||
<RainTimeRangeBar
|
||||
value={rainTimePreset}
|
||||
disabled={voiceDisabled}
|
||||
onChange={setRainTimePreset}
|
||||
/>
|
||||
)}
|
||||
<div className={`chat-input-row${showHomeWelcome ? ' chat-input-row-home' : ''}`}>
|
||||
<div className={`chat-input-shell${showHomeWelcome ? ' chat-input-shell-home' : ''}`}>
|
||||
{canUpload && (
|
||||
@@ -1343,6 +1364,12 @@ export function ChatPanel({
|
||||
}
|
||||
pendingSkillRef.current = skillId ?? null;
|
||||
setActiveTemplatePrefill(null);
|
||||
if (skillId === RAIN_SKILL_ID) {
|
||||
setActiveRainSkill(true);
|
||||
setRainTimePreset(DEFAULT_RAIN_TIME_PRESET);
|
||||
} else {
|
||||
setActiveRainSkill(false);
|
||||
}
|
||||
setInput((current) => mergeChatSkillPromptWithInput(prompt, current));
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -588,6 +588,7 @@ export function ChatView({
|
||||
pgRequired: options?.pgRequired,
|
||||
imageGenerationMode: options?.imageGenerationMode,
|
||||
selectedChatSkill: options?.selectedChatSkill,
|
||||
rainTimePreset: options?.rainTimePreset,
|
||||
fileAttachments: options?.fileAttachments,
|
||||
},
|
||||
imageUrls,
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import {
|
||||
DEFAULT_RAIN_TIME_PRESET,
|
||||
RAIN_TIME_PRESET_OPTIONS,
|
||||
type RainTimePresetId,
|
||||
} from '../utils/rainTimeRange';
|
||||
|
||||
export function RainTimeRangeBar({
|
||||
value,
|
||||
disabled,
|
||||
onChange,
|
||||
}: {
|
||||
value?: RainTimePresetId;
|
||||
disabled?: boolean;
|
||||
onChange: (preset: RainTimePresetId) => void;
|
||||
}) {
|
||||
const active = value ?? DEFAULT_RAIN_TIME_PRESET;
|
||||
|
||||
return (
|
||||
<div className="rain-time-range-bar" role="group" aria-label="Rain 分析时间范围">
|
||||
<span className="rain-time-range-bar-label">时间范围</span>
|
||||
<div className="rain-time-range-bar-options">
|
||||
{RAIN_TIME_PRESET_OPTIONS.map((option) => (
|
||||
<button
|
||||
key={option.id}
|
||||
type="button"
|
||||
className={`rain-time-range-option${active === option.id ? ' is-active' : ''}`}
|
||||
disabled={disabled}
|
||||
aria-pressed={active === option.id}
|
||||
onClick={() => onChange(option.id)}
|
||||
>
|
||||
{option.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -100,6 +100,7 @@ type ChatSubmitOptions = {
|
||||
pgRequired?: boolean;
|
||||
imageGenerationMode?: ImageGenerationMode;
|
||||
selectedChatSkill?: string;
|
||||
rainTimePreset?: import('../utils/rainTimeRange').RainTimePresetId;
|
||||
fileAttachments?: ChatFileAttachment[];
|
||||
goalRunId?: string;
|
||||
};
|
||||
@@ -1874,6 +1875,7 @@ export function useTKMindChat(
|
||||
...(options?.pgRequired ? { pgRequired: true } : {}),
|
||||
imageGenerationMode: options?.imageGenerationMode ?? 'auto',
|
||||
...(options?.selectedChatSkill ? { selectedChatSkill: options.selectedChatSkill } : {}),
|
||||
...(options?.rainTimePreset ? { rainTimePreset: options.rainTimePreset } : {}),
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -3162,6 +3162,59 @@ body,
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.rain-time-range-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin: 0 0 8px;
|
||||
padding: 8px 10px;
|
||||
border: 1px solid var(--color-border-input);
|
||||
border-radius: var(--radius-lg);
|
||||
background: var(--color-bg-elevated);
|
||||
}
|
||||
|
||||
.rain-time-range-bar-label {
|
||||
flex: 0 0 auto;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: var(--color-text-secondary);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.rain-time-range-bar-options {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.rain-time-range-option {
|
||||
min-height: 28px;
|
||||
padding: 4px 10px;
|
||||
border: 1px solid var(--color-border-input);
|
||||
border-radius: 999px;
|
||||
background: transparent;
|
||||
color: var(--color-text-secondary);
|
||||
font: inherit;
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.rain-time-range-option:hover:not(:disabled) {
|
||||
color: var(--color-text-primary);
|
||||
border-color: var(--color-border-strong, var(--color-border-input));
|
||||
}
|
||||
|
||||
.rain-time-range-option.is-active {
|
||||
color: var(--color-text-primary);
|
||||
border-color: rgba(121, 146, 255, 0.55);
|
||||
background: rgba(121, 146, 255, 0.12);
|
||||
}
|
||||
|
||||
.rain-time-range-option:disabled {
|
||||
opacity: 0.55;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.chat-deep-reasoning-toggle {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
export type RainTimePresetId = 'today' | 'yesterday' | '3d' | '7d';
|
||||
|
||||
export const RAIN_SKILL_ID = 'rain';
|
||||
|
||||
export const RAIN_TIME_PRESET_OPTIONS: ReadonlyArray<{ id: RainTimePresetId; label: string }> = [
|
||||
{ id: 'today', label: '今天' },
|
||||
{ id: 'yesterday', label: '昨天' },
|
||||
{ id: '3d', label: '近3天' },
|
||||
{ id: '7d', label: '近7天' },
|
||||
];
|
||||
|
||||
export const DEFAULT_RAIN_TIME_PRESET: RainTimePresetId = '3d';
|
||||
Reference in New Issue
Block a user