Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 21 additions & 14 deletions app/apps/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ import { useCurrentUser } from "@/hooks/useCurrentUser";
import { checkSuperAdmin } from "@/lib/clientPermissions";
import WorkflowEditor from "./components/WorkflowEditor";
import { syncFormToWorkflow } from "@/lib/workflowUtils";
import { resolveAutoSelectDatasets } from "@/lib/appDatasets";
import { WorkflowConfig } from "@/types/workflow";
import { DEFAULT_LLM_MODEL_CODE, type LlmModelOption } from "@/lib/llmModels";

Expand Down Expand Up @@ -466,8 +467,7 @@ export default function AppsPage() {
settings: app.settings || {},
is_default: app.is_default || false,
});
// 如果 dataset_ids 为空,则自动选择知识库为 true,否则为 false
setAutoSelectDatasets(datasetIds.length === 0);
setAutoSelectDatasets(resolveAutoSelectDatasets(app.settings, datasetIds));

setDialogOpen(true);
}, []);
Expand All @@ -482,12 +482,18 @@ export default function AppsPage() {
try {
setSubmitting(true);

const workflow = syncFormToWorkflow({ ...formData }, editingApp?.settings?.workflow, datasets);
const workflow = syncFormToWorkflow(
{ ...formData },
editingApp?.settings?.workflow,
datasets
);
const submitData = {
...formData,
dataset_ids: autoSelectDatasets ? [] : formData.dataset_ids,
settings: {
...formData.settings,
workflow,
auto_select_datasets: autoSelectDatasets,
},
};

Expand All @@ -514,7 +520,7 @@ export default function AppsPage() {
} finally {
setSubmitting(false);
}
}, [formData, editingApp, loadApps, datasets]);
}, [formData, autoSelectDatasets, editingApp, loadApps, datasets]);

// 提交应用审核(draft/rejected → pending_review;建即 draft,仅 owner 可测)
const handleSubmitAppReview = useCallback(
Expand Down Expand Up @@ -926,10 +932,10 @@ export default function AppsPage() {
<div className="text-sm">
<div className="flex items-center gap-4">
{/* 数据集为 0 不显示。
0 不是"没有知识库"——`dataset_ids` 为空时后端走
空 `dataset_ids` 加上自动选择开关(settings.auto_select_datasets,
未存过则默认开)时,后端走
`kb_classifier_service.select_relevant_datasets(user_id=...)`,
在该用户有权限的**所有**知识库里智能选(auto_select_kb)。
所以 0 表示的是默认行为,把它显示成 0 会读成"这个员工没知识"。*/}
在该用户有权限的知识库里智能选。把它显示成 0 会读成"这个员工没知识"。*/}
{(app.dataset_ids?.length || 0) > 0 && (
<div className="flex items-center gap-2">
<span className="text-muted-foreground">{t("datasets")}</span>
Expand Down Expand Up @@ -1364,13 +1370,14 @@ export default function AppsPage() {
onCheckedChange={(checked) => {
const isChecked = checked === true;
setAutoSelectDatasets(isChecked);
// 如果勾选了自动选择知识库,清空所有已选择的知识库
if (isChecked) {
setFormData({
...formData,
dataset_ids: [],
});
}
setFormData({
...formData,
dataset_ids: isChecked ? [] : formData.dataset_ids,
settings: {
...formData.settings,
auto_select_datasets: isChecked,
},
});
}}
/>
<label
Expand Down
19 changes: 19 additions & 0 deletions lib/appDatasets.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* 应用「自动选择知识库」开关。
*
* 不能只用 dataset_ids 是否为空来推断:取消勾选后如果不选具体库,保存的仍是空数组,
* 下次打开会被当成「自动选择」。开关本身存在 apps.settings.auto_select_datasets。
*/
export function resolveAutoSelectDatasets(
settings?: Record<string, unknown> | null,
datasetIds?: string[] | null
): boolean {
if (datasetIds && datasetIds.length > 0) {
return false;
}
const stored = settings?.auto_select_datasets;
if (typeof stored === "boolean") {
return stored;
}
return true;
}
32 changes: 32 additions & 0 deletions test/appAutoSelectDatasets.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { test } from "node:test";
import { resolveAutoSelectDatasets } from "../lib/appDatasets.ts";

test("绑了知识库时一定不是自动选择", () => {
assert.equal(resolveAutoSelectDatasets({ auto_select_datasets: true }, ["ds-1"]), false);
assert.equal(resolveAutoSelectDatasets(undefined, ["ds-1"]), false);
});

test("未绑知识库时以 settings 里存下的开关为准", () => {
assert.equal(resolveAutoSelectDatasets({ auto_select_datasets: false }, []), false);
assert.equal(resolveAutoSelectDatasets({ auto_select_datasets: true }, []), true);
assert.equal(resolveAutoSelectDatasets({ auto_select_datasets: false }, undefined), false);
});

test("存量应用没存过开关时,空 dataset_ids 仍视为自动选择", () => {
assert.equal(resolveAutoSelectDatasets({}, []), true);
assert.equal(resolveAutoSelectDatasets(undefined, []), true);
assert.equal(resolveAutoSelectDatasets(null, null), true);
});

test("应用编辑页保存并回填自动选择知识库开关", () => {
const src = readFileSync(new URL("../app/apps/page.tsx", import.meta.url), "utf8");
assert.match(src, /resolveAutoSelectDatasets/);
assert.match(src, /auto_select_datasets:\s*autoSelectDatasets/);
assert.doesNotMatch(
src,
/setAutoSelectDatasets\(datasetIds\.length === 0\)/,
"不能再用空 dataset_ids 推断开关,否则取消勾选记不住"
);
});
Loading