fix(会商第三步): 流程图入库限 rwfx-A + 修复跳过报告生成流程图出现双调度中卡片

- 入库功能仅 rwfx-A(businessCode 6BF)深链会商模式提供,其它业务深链生成流程图不再出现入库按钮/询问
- 流程图抽取串行化:auto 自动出图与用户「跳过报告直接生成流程图」手动出图竞态时,先中止上一轮、复用/移除被取代气泡,保证任意时刻只有一张流程图卡片

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
fengxiangdebaoziandClaude Opus 4.8 committed 2026-06-25 12:29:45 +08:00
1 parent 04e6d0aa00
commit 893f1e6933
19 files changed
+559 -51

No files matched your search

+47 -1
View File
@@ -20,6 +20,7 @@ import {
readCopTaskDetail,
resolveTaskDeeplinkTarget,
} from "@/core/auth/task-deeplink";
import { readUserInfo } from "@/strategy-components/lib/light-app";
/** 「大屏绘制」独立页应用内路由(深链「上一步」默认指向它,跳转追加 ?taskId=)。 */
export const DASHBOARD_AGENT_ROUTE = "/page/strategy/dashboard-agent";
@@ -66,6 +67,20 @@ export type TaskButtonIdKind = "task" | "action";
/** ``url`` 外链打开方式:``blank``=新窗口(默认)/ ``self``=当前窗口(嵌入态即当前 iframe)。 */
export type TaskButtonOpenMode = "blank" | "self";
/**
* ``url`` 外链追加的**登录参数**(与「应用管理」一致):在拼好的跳转地址后再依次
* 追加 ``?{key}={value}``,``value`` 运行时从 ``userInfo`` 按 ``source`` 解析
* (``other`` 时取 ``customValue`` 字面值)。复用 [[light-app-center]] 的取值来源。
*/
export interface TaskButtonLoginParam {
/** 拼到 URL 的查询参数名。 */
key: string;
/** 取值来源:``userInfo`` 字段名(如 ``accessToken`` / ``yUserId``)或 ``other``(自填)。 */
source: string;
/** ``source==="other"`` 时的自定义字面值。 */
customValue: string;
}
/** 一个可配置跳转按钮。 */
export interface TaskButton {
id: string;
@@ -85,10 +100,25 @@ export interface TaskButton {
idKind: TaskButtonIdKind;
/** ``url`` 外链打开方式:``blank``=新窗口(默认)/ ``self``=当前窗口。仅 ``url`` 类型有意义。 */
openMode: TaskButtonOpenMode;
/** ``url`` 外链追加的登录参数列表(仅 ``url`` 类型有意义;为空则不追加,行为同旧版)。 */
loginParams: TaskButtonLoginParam[];
enabled: boolean;
sortOrder: number;
}
/** 运行时解析单个登录参数的值(``other`` 取字面值,否则从 ``userInfo`` 取 ``source`` 字段)。 */
function resolveLoginParamValue(
p: TaskButtonLoginParam,
userInfo: Record<string, unknown>,
): string {
if (p.source === "other") return p.customValue ?? "";
if (p.source) {
const value = userInfo[p.source];
return value == null ? "" : String(value);
}
return "";
}
/** 内部切换可选的目标业务(``business`` 类型按钮的下拉项)。 */
export const TASK_BUSINESS_TARGETS: { code: TaskBusiness; label: string }[] = [
{ code: "3qfx", label: "三情分析" },
@@ -120,6 +150,7 @@ export function defaultTaskButtons(cfg: TaskDeeplinkConfig): TaskButton[] {
idParam: "id",
idKind: "task",
openMode: "blank",
loginParams: [],
enabled: true,
sortOrder,
});
@@ -134,6 +165,7 @@ export function defaultTaskButtons(cfg: TaskDeeplinkConfig): TaskButton[] {
idParam: "id",
idKind: "task",
openMode: "blank",
loginParams: [],
enabled: true,
sortOrder,
});
@@ -149,6 +181,7 @@ export function defaultTaskButtons(cfg: TaskDeeplinkConfig): TaskButton[] {
idParam: "id",
idKind: "task",
openMode: "blank",
loginParams: [],
enabled: true,
sortOrder: 0,
},
@@ -167,6 +200,7 @@ export function defaultTaskButtons(cfg: TaskDeeplinkConfig): TaskButton[] {
idParam: "taskId",
idKind: "task",
openMode: "self",
loginParams: [],
enabled: true,
sortOrder: 1,
},
@@ -180,6 +214,7 @@ export function defaultTaskButtons(cfg: TaskDeeplinkConfig): TaskButton[] {
idParam: "id",
idKind: "task",
openMode: "blank",
loginParams: [],
enabled: true,
sortOrder: 2,
},
@@ -193,6 +228,7 @@ export function defaultTaskButtons(cfg: TaskDeeplinkConfig): TaskButton[] {
idParam: "id",
idKind: "task",
openMode: "blank",
loginParams: [],
enabled: true,
sortOrder: 3,
},
@@ -259,7 +295,17 @@ export async function runTaskButton(btn: TaskButton, ctx: RunTaskButtonCtx): Pro
// 行动分析(xdfx)可选追加行动id;否则用任务id。行动id 缺失时回退任务id。
const id = btn.idKind === "action" ? ctx.actionId || ctx.taskId : ctx.taskId;
const param = (btn.idParam || "id").trim() || "id";
const url = btn.appendTaskId && id ? appendQueryParam(base, param, id) : base;
let url = btn.appendTaskId && id ? appendQueryParam(base, param, id) : base;
// 追加登录参数(与应用管理一致):运行时从 userInfo 解析每项的值后拼到地址尾部。
const loginParams = btn.loginParams ?? [];
if (loginParams.length > 0) {
const userInfo = readUserInfo();
for (const lp of loginParams) {
const key = (lp.key || "").trim();
if (!key) continue;
url = appendQueryParam(url, key, resolveLoginParamValue(lp, userInfo));
}
}
// 应用内部路由(以单个 / 开头,如「上一步」→ 大屏绘制页):
// self → 走 react-router 同窗导航(不刷新、保留 SPA);blank → 拼成当前源的 hash 路由新标签打开。
if (base.startsWith("/") && !base.startsWith("//")) {