schedules.ts
7.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
/*
* @Author: AI Assistant
* @Date: 2025-11-25
* @LastEditors: 赵丽婷
* @LastEditTime: 2026-01-19 17:59:53
* @FilePath: \LinkMed\linkmed-vue3\src\stores\schedules.ts
* @Description: 定时任务状态管理
* Copyright (c) 2025 by 北京连心医疗科技有限公司, All Rights Reserved.
*/
import { defineStore } from "pinia";
import { ref } from "vue";
import { createSchedule, type CreateSchedulePayload } from "@/api/schedules";
import { getUserProfile } from "@/api/user";
import { useDeerFlowStore } from "@/stores/deerflow";
import { useSettingsStore } from "@/stores/settings";
export const useSchedulesStore = defineStore("schedules", () => {
// State - 存储从组件传递的字段
const startTask = ref<boolean>(false);
const startTime = ref<string>("");
const notifyType = ref<string>("");
const repeatType = ref<string | undefined>(undefined);
const repeatExpr = ref<string | undefined>(undefined);
const repeatEndTime = ref<string | undefined>(undefined);
const description = ref<string>("");
const scheduleId = ref<number | undefined>(undefined); // 任务Id
// 加载状态
const loading = ref(false);
const error = ref<string | null>(null);
const deerflowStore = useDeerFlowStore();
const settingsStore = useSettingsStore();
/**
* 设置定时任务基础信息
* 从组件中接收的核心字段
*/
function setScheduleInfo(info: {
startTime: string;
notifyType: string;
repeatType?: string;
repeatExpr?: string;
repeatEndTime?: string;
}) {
startTime.value = info.startTime;
notifyType.value = info.notifyType;
repeatType.value = info.repeatType;
repeatExpr.value = info.repeatExpr;
repeatEndTime.value = info.repeatEndTime;
}
/**
* 获取用户邮箱
*/
async function getUserEmail(): Promise<string> {
try {
const userProfile = await getUserProfile();
if (userProfile && userProfile.email) {
return userProfile.email;
}
} catch (error) {
console.error("获取用户邮箱失败:", error);
}
return "";
}
/**
* 构建深度检索接口的 params 参数
*/
function buildParams(mode?: "fast" | "standard" | "deep") {
// 构建 messages 数组
const messages = [
{
role: "user",
content: description.value || "",
},
];
// 构建 高级筛选 内容
const realThreadId = deerflowStore?.currentThreadId || "";
// 构建 literature_filters 参数
const filters = settingsStore.getLiteratureFilters() || [];
const dateRange = settingsStore.getLiteratureDateRange();
// 判断是否启用了知识库
const isKnowledgeBaseEnabled = !!settingsStore.selectedKnowledgeBaseDirectory;
// 将 literatureFilters 转换为只包含 key 和 selected 的格式,只保留 key 为 "dataSource" 的项
const literatureFiltersFormatted = filters
.filter((filter) => filter.key === "dataSource")
.map((filter) => {
// 如果启用了知识库,数据源应为空;否则如果没有选择,默认使用 pubmed
let selected = isKnowledgeBaseEnabled
? []
: filter.selected && filter.selected.length > 0
? filter.selected
: ["pubmed"];
// 强制过滤掉 medRxiv,不影响正常功能
selected = selected.filter((id: string) => id !== "medRxiv");
// 如果过滤后为空且未启用知识库,确保至少有 pubmed
if (selected.length === 0 && !isKnowledgeBaseEnabled) {
selected = ["pubmed"];
}
return {
key: filter.key || "dataSource",
selected: selected,
};
});
// 构建 literature_filters 对象
const literature_filters: any = {
literatureFilters: literatureFiltersFormatted,
};
// 如果有日期范围,添加到结果中
if (dateRange && Array.isArray(dateRange) && dateRange.length === 2) {
literature_filters.literatureDateRange = dateRange;
}
// 构建完整的 params 对象(深度检索接口参数)
return {
messages,
resources: [],
debug: false,
thread_id: realThreadId,
...(mode ? { mode } : {}),
max_plan_iterations: settingsStore.maxPlanIterations,
max_step_num: settingsStore.maxStepNum,
max_search_results: settingsStore.maxSearchResults,
auto_accepted_plan: true,
interrupt_feedback: null,
enable_background_investigation: true,
report_style: "academic",
enable_deep_thinking: false,
literature_filters,
use_surveyx: isKnowledgeBaseEnabled,
file_ids: isKnowledgeBaseEnabled
? settingsStore.knowledgeBaseFileIds.map((id) => "prod" + id)
: [],
};
}
/**
* 构建 createSchedule 的 payload 参数
*/
async function buildPayload(
mode?: "fast" | "standard" | "deep",
): Promise<CreateSchedulePayload> {
// // 获取用户邮箱
// const userEmail = await getUserEmail();
// 构建 params(深度检索接口参数)
const params = buildParams(mode);
// 截断 title 字段,最多 200 个字符
const title =
description.value.length > 200
? description.value.substring(0, 200)
: description.value;
// 构建 payload
const payload: CreateSchedulePayload = {
title: title,
question: description.value,
startTime: startTime.value,
repeatType: repeatType.value,
repeatExpr: repeatExpr.value,
repeatEndTime: repeatEndTime.value,
notifyType: "all",
notifyTo: undefined,
params: params,
};
return payload;
}
/**
* 创建定时任务
* 调用 API 接口
*/
async function createScheduleTask(mode?: "fast" | "standard" | "deep") {
try {
loading.value = true;
error.value = null;
// 验证必填字段
if (!startTime.value) {
throw new Error("开始时间不能为空");
}
if (!description.value || description.value.trim() === "") {
throw new Error("描述不能为空");
}
// // 如果需要邮件通知,检查用户邮箱
// if (notifyType.value === "email") {
// const userEmail = await getUserEmail();
// if (!userEmail) {
// throw new Error("无法获取用户邮箱,请绑定邮箱");
// }
// }
// 构建 payload
const payload = await buildPayload(mode);
// 调用创建定时任务接口
// 接口返回形式:HTTP 状态码 200,响应体为可选的 integer <int64>(任务ID)
const response = await createSchedule(payload);
// response.data 直接是任务ID(数字),如果存在则创建成功
const taskId = response.data;
if (taskId !== undefined && taskId !== null) {
return {
success: true,
data: { id: taskId }, // 为了保持向后兼容,包装成对象
message: "定时任务创建成功",
};
} else {
throw new Error("创建定时任务失败:未返回任务ID");
}
} catch (err: any) {
error.value = err?.message || "创建定时任务失败";
console.error("创建定时任务失败:", err);
return {
success: false,
data: null,
message:
err?.response?.data?.message || err?.message || "创建定时任务失败",
};
} finally {
loading.value = false;
}
}
/**
* 重置状态
*/
function resetScheduleInfo() {
startTime.value = "";
notifyType.value = "";
repeatType.value = undefined;
repeatExpr.value = undefined;
repeatEndTime.value = undefined;
description.value = "";
error.value = null;
}
return {
// state
startTask,
startTime,
notifyType,
repeatType,
repeatExpr,
repeatEndTime,
description,
loading,
error,
scheduleId,
// actions
setScheduleInfo,
buildPayload,
buildParams,
createScheduleTask,
resetScheduleInfo,
getUserEmail,
};
});