@@ -7865,7 +7865,7 @@ function openPreferredModelAction() {
const gatewayModels = safeArray(localCatalog.models).map((item) => item.id).filter(Boolean);
openActionModal({
title: "设置分析主模型",
- description: "后续导入分析、市场调研和风格学习会优先使用这里设置的模型。",
+ description: "导入分析、市场调研和风格学习都会优先使用这里设置的模型。",
submitLabel: "保存模型",
fields: [
{
@@ -8762,7 +8762,7 @@ function openTrackSelectedAccountAction() {
title: trackedItem ? "更新跟踪账号" : "加入跟踪",
description: trackedItem
? "这个账号已经在跟踪中,可以切换负责 Agent 或补充备注。"
- : "把当前对标账号加入每日跟踪,后续自动生成更新日报。",
+ : "把当前对标账号加入每日跟踪,系统会自动生成更新日报。",
submitLabel: trackedItem ? "保存跟踪" : "开始跟踪",
fields: [
{ name: "accountName", label: "账号", type: "html", html: `
${escapeHtml(getAccountName(account) || "未命名账号")}${escapeHtml(getAccountProfileUrl(account) || account.signature || "")}
` },
@@ -9343,7 +9343,7 @@ function openSystemMainPolicyAction() {
const current = bundle.current_version || {};
openActionModal({
title: "编辑系统主 Agent 策略",
- description: "这是所有用户共享的系统级主 Agent 基座能力,后续用户层和管理员覆盖都会叠加在它上面。",
+ description: "这是所有用户共享的系统级主 Agent 基座能力,用户层和管理员覆盖都会叠加在它上面。",
submitLabel: "保存系统策略",
fields: [
{ type: "html", label: "当前版本", html: renderPolicyVersionSummary(bundle, "系统主 Agent 还没有系统默认策略。") },
@@ -10098,7 +10098,7 @@ function openCreateAssistantAction() {
{ name: "name", label: "名称", placeholder: "例如:创业成交助手" },
{ name: "description", label: "说明", placeholder: "例如:服务创业 IP 与成交型短视频" },
{ name: "goal", label: "生成目标", placeholder: "例如:输出创业口播、对标拆解和成交文案" },
- { name: "systemPrompt", label: "系统提示词", type: "textarea", rows: 5, placeholder: "可选,不填则后续再补" },
+ { name: "systemPrompt", label: "系统提示词", type: "textarea", rows: 5, placeholder: "可选,可先留空,后面随时补充" },
{ name: "knowledgeBaseId", label: "默认知识库", type: "select", value: kbOptions[0]?.value || "", options: [{ value: "", label: "暂不绑定" }, ...kbOptions] },
{ name: "modelProfileId", label: "主模型", type: "select", value: modelOptions.find((item) => item.value === safeArray(appState.dashboard?.model_profiles).find((m) => m.is_default)?.id)?.value || modelOptions[0]?.value || "", options: modelOptions }
],
@@ -10141,7 +10141,7 @@ function openEditAssistantAction(assistantId = "") {
{ name: "name", label: "名称", value: assistant.name || "", placeholder: "例如:创业成交助手" },
{ name: "description", label: "说明", value: assistant.description || "", placeholder: "例如:服务创业 IP 与成交型短视频" },
{ name: "goal", label: "生成目标", value: assistant.generation_goal || "", placeholder: "例如:输出创业口播、对标拆解和成交文案" },
- { name: "systemPrompt", label: "系统提示词", type: "textarea", rows: 5, value: assistant.system_prompt || "", placeholder: "可选,不填则后续再补" },
+ { name: "systemPrompt", label: "系统提示词", type: "textarea", rows: 5, value: assistant.system_prompt || "", placeholder: "可选,可先留空,后面随时补充" },
{ name: "modelProfileId", label: "主模型", type: "select", value: assistant.model_profile_id || modelOptions[0]?.value || "", options: modelOptions }
],
onSubmit: async (values) => {
@@ -10289,7 +10289,7 @@ function openBenchmarkLinkAction(defaults = {}) {
: null;
openActionModal({
title: "保存对标关系",
- description: "把当前账号和另一个账号关联成对标关系,便于后续持续跟踪。",
+ description: "把当前账号和另一个账号关联成对标关系,便于持续跟踪。",
submitLabel: "保存关系",
fields: [
{ name: "targetAccountId", label: "目标账号", type: "select", value: defaults.targetAccountId || candidate?.candidate_account_id || options[0]?.value || "", options: [{ value: "", label: "仅保存主页链接" }, ...options] },
@@ -11220,7 +11220,7 @@ function openReviewAction(defaults = {}) {
title: existingReview ? "编辑复盘" : "写复盘",
description: existingReview
? "补充表现数据、判断和下一步动作,持续迭代项目策略。"
- : "把完成任务写成一条可追踪复盘,后续可按项目累计。",
+ : "把完成任务写成一条可追踪复盘,可按项目累计。",
submitLabel: existingReview ? "保存复盘" : "创建复盘",
fields: [
{ name: "title", label: "标题", value: existingReview?.title || defaults.title || sourceJob?.title || "", placeholder: "例如:创业口播 3 月 22 日复盘" },
@@ -11891,20 +11891,11 @@ document.addEventListener("click", async (event) => {
return;
}
if (name === "select-project") {
- appState.selectedProjectId = action.dataset.projectId || "";
- setBusy(true, "正在切换项目视图...");
try {
- await loadStorageStatus(appState.selectedProjectId || "");
- await loadAgentControlSurfaces(appState.selectedProjectId || "");
- if (appState.selectedOnelinerSessionId) {
- await loadOneLinerMessages(appState.selectedOnelinerSessionId);
- } else {
- appState.onelinerMessages = [];
- }
- } finally {
- setBusy(false, "");
+ await applySelectedProject(action.dataset.projectId || "");
+ } catch (error) {
+ presentActionFailure(error, "切换项目失败");
}
- renderAll();
return;
}
if (name === "select-platform") {
diff --git a/web/storyforge-web-v4/tests/workbench-pages.test.mjs b/web/storyforge-web-v4/tests/workbench-pages.test.mjs
index 4bbc1f7..5106faf 100644
--- a/web/storyforge-web-v4/tests/workbench-pages.test.mjs
+++ b/web/storyforge-web-v4/tests/workbench-pages.test.mjs
@@ -135,6 +135,7 @@ test("project creation and switching use in-app sheets instead of browser prompt
test("mobile project sheets support direct project picking and zoom-safe form controls", () => {
const projectSwitcher = extractBetween(APP, "function openDashboardProjectSwitcher()", "function openDashboardActionReasonAction(");
const applySelectedProject = extractBetween(APP, "async function applySelectedProject(projectId = \"\")", "function openDashboardProjectSwitcher()");
+ const clickHandler = extractBetween(APP, "document.addEventListener(\"click\", async (event) => {", "document.addEventListener(\"submit\", async (event) => {");
const createProject = extractBetween(APP, "async function createProject()", "function openPreferredModelAction()");
assert.match(APP, /async function applySelectedProject\(projectId = ""\)/);
assert.match(APP, /function focusDashboardWorkspace\(anchorId = "dashboard-workspace-anchor"\)/);
@@ -150,6 +151,7 @@ test("mobile project sheets support direct project picking and zoom-safe form co
assert.match(applySelectedProject, /loadStorageStatus\(appState\.selectedProjectId \|\| ""\)/);
assert.match(applySelectedProject, /loadAgentControlSurfaces\(appState\.selectedProjectId \|\| ""\)/);
assert.match(applySelectedProject, /focusDashboardWorkspace\("dashboard-workspace-anchor"\)/);
+ assert.match(clickHandler, /name === "select-project"[\s\S]*await applySelectedProject\(action\.dataset\.projectId \|\| ""\)/);
assert.match(APP, /id="dashboard-workspace-anchor"/);
assert.match(createProject, /onOpen:\s*\(/);
assert.match(CSS, /@media \(max-width: 760px\)[\s\S]*\.field-stack input,\s*[\s\S]*\.field-stack textarea,\s*[\s\S]*\.field-stack select\s*\{[\s\S]*min-height:\s*46px/);
@@ -385,6 +387,17 @@ test("discovery and production screens expose compact mobile flow summaries", ()
assert.match(production, /失败/);
});
+test("workbench copy uses direct live language instead of future-placeholder wording", () => {
+ assert.doesNotMatch(APP, /可选,不填则后续再补/);
+ assert.match(APP, /可选,可先留空,后面随时补充/);
+ assert.match(APP, /文案生成、对标绑定和复盘都会优先使用这里选中的 Agent/);
+ assert.match(APP, /导入分析、市场调研和风格学习都会优先使用这里设置的模型/);
+ assert.match(APP, /系统会自动生成更新日报/);
+ assert.match(APP, /把完成任务写成一条可追踪复盘,可按项目累计/);
+ assert.match(APP, /先绑定执行 Agent,再完善任务目标和方法论/);
+ assert.match(APP, /先看真实作品,再继续整理文档与成片/);
+});
+
test("discovery and production screens expose mobile focus cards with next-step actions", () => {
const discovery = extractBetween(APP, "function renderDiscoveryScreen()", "function renderTrackingScreen()");
const production = extractBetween(APP, "function renderProductionScreen()", "function renderReviewScreen()");