Files
吉鑫升andClaude Opus 4.8 58357547c9 Merge branch 'ji' into master
按钮管理「登录参数」两套实现冲突解决——两分支各自独立给跳转按钮加了登录态追加能力,
二者正交、保留两套,互不影响:
- master: login_params (JSON 列 login_params_json,从 userInfo 解析,类似轻应用登录参数)
- ji: append_auth + auth_token_param + auth_name_param (token 登录时追加 token1+用户名)

迁移 revision 碰撞修复(两分支都用了 20260625_01):重编号为线性链
  20260620_02 → 20260625_01 (login_params) → 20260625_02 (auth_params) → 20260625_03 (users_approved)
并同步 column_additions_mysql.sql 注释里的 migration 编号。

前后端 task_buttons(model/sql/memory/router/前端 type·api·admin 页)均保留两套字段;
两份 CLAUDE.md 文档合并为同时记录两种机制。

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

71 lines
4.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""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, PortableJSON
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")
# ``url`` 外链追加的登录参数(与应用管理一致):在拼好的地址后再依次追加
# ``?{key}={value}``,``value`` 由前端运行时从 ``userInfo`` 按 ``source`` 解析
# (``other`` 时取 ``custom_value`` 字面值)。每项 ``{key, source, custom_value}``。
# 旧行 / NULL 读时归一化为 ``[]``。
login_params_json: Mapped[list] = mapped_column(PortableJSON(), default=list)
# ``url`` 跳转是否追加登录态(token 登录的上游 token + 登录用户名),供外链所在的外部系统
# 校验当前登录用户。仅 token 登录(前端存有 token1)时实际拼上;非 token 登录自动跳过。
# ``server_default`` 必须显式声明:否则在已存在 ``task_buttons`` 表的旧库上,
# 启动期自动补列 ``_ensure_orm_columns_sync`` 会跳过「NOT NULL 且无 server_default」
# 的列(见 engine.py),导致该列永远补不上 → GET 查询报 Unknown column → 500。
append_auth: Mapped[bool] = mapped_column(Boolean, default=False, server_default="0")
# 追加 token / 用户名的查询参数名。可空,读时归一化为 ``token`` / ``username``。
auth_token_param: Mapped[str | None] = mapped_column(String(64), default="token")
auth_name_param: Mapped[str | None] = mapped_column(String(64), default="username")
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)
)