Files
fengxiangdebaoziandClaude Opus 4.8 a9f01bec79 feat(task-buttons): 外链按钮新增「打开方式」(新窗口/当前窗口)
按钮管理(/page/strategy/admin/task-buttons)的 url 外链按钮可配置打开方式:
- blank=新窗口(默认,window.open(_blank),行为同改前)
- self=当前窗口(window.location.assign,嵌入态即当前 iframe)

新增 TaskButton.openMode 字段贯通前后端:前端 task-buttons.ts 类型+种子+
runTaskButton 打开逻辑、api 客户端 snake⇄camel 映射、TaskButtonsPage 下拉;
后端 router schema + ORM open_mode 列(可空默认 blank,启动自动 ALTER 补列,
无需手动迁移)+ sql/memory store 归一化。仅 url 类型生效。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 16:09:01 +08:00

57 lines
2.8 KiB
Python

"""ORM model for task-workspace configurable jump buttons (按钮管理).
Global / shared — there is no ``user_id`` scoping; every account sees the same
buttons. The task deep-link workspaces (rwfx / 3qfx / xdfx, see
``TaskFxWorkspace``) render the enabled buttons for their ``business`` in the
left task panel. Each row is one button:
- ``business`` — which workspace the button belongs to (``rwfx`` / ``3qfx`` /
``xdfx``).
- ``label`` — display name.
- ``link_type`` — ``url`` (external, opened in a new tab) or ``business``
(internal switch to another deep-link business).
- ``target`` — the full URL (``url``) or the target business code (``business``).
- ``append_task_id`` — for ``url`` buttons, whether to append ``?id={taskId}``.
- ``enabled`` — 停用 parks a button without deleting it.
- ``sort_order`` — position among the business's buttons.
When the whole table is empty (fresh deployment, never saved) the frontend
falls back to code-defined seed defaults built from the live task-deeplink
config; once saved, this table is the source of truth. ``updated_by`` is
audit-only.
"""
from __future__ import annotations
from datetime import UTC, datetime
from sqlalchemy import Boolean, Integer, String
from sqlalchemy.orm import Mapped, mapped_column
from deerflow.persistence.base import Base
from deerflow.persistence.types import BeijingDateTime
class TaskButtonRow(Base):
__tablename__ = "task_buttons"
id: Mapped[str] = mapped_column(String(128), primary_key=True)
business: Mapped[str] = mapped_column(String(32), index=True)
label: Mapped[str] = mapped_column(String(255), default="")
link_type: Mapped[str] = mapped_column(String(16), default="url")
target: Mapped[str] = mapped_column(String(1024), default="")
append_task_id: Mapped[bool] = mapped_column(Boolean, default=True)
# 追加的查询参数名(如 ``id`` / ``task_id``)。可空,读时归一化为 ``id``。
id_param: Mapped[str | None] = mapped_column(String(64), default="id")
# 追加的 id 取哪种:``task``=任务id(默认)/ ``action``=行动id(仅 xdfx 二者不同:深链原始
# ?taskId= 实为行动id,任务id 由 action 接口解析)。可空,读时归一化为 ``task``。
id_kind: Mapped[str | None] = mapped_column(String(16), default="task")
# ``url`` 外链打开方式:``blank``=新窗口(默认)/ ``self``=当前窗口。可空,读时归一化为 ``blank``。
open_mode: Mapped[str | None] = mapped_column(String(16), default="blank")
enabled: Mapped[bool] = mapped_column(Boolean, default=True)
sort_order: Mapped[int] = mapped_column(Integer, default=0)
updated_by: Mapped[str | None] = mapped_column(String(64))
updated_at: Mapped[datetime] = mapped_column(
BeijingDateTime(), default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC)
)