feat(agents): 智能体归属/发布操作前增加「账号已切换」提醒
- 新增 useLiveAccount 钩子:跟踪「实时」登录账号(随 storage/focus 刷新), 并与组件挂载时捕获的账号对比;token 存 localStorage 会被同浏览器其他标签页 共享,另一标签页登录会静默替换本页 API 所用账号 - agent-card / agent-detail-panel / publish-square-picker-dialog / NewAgentPage 接入该钩子,切换账号后对归属/发布类操作做提醒,避免误归属 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
2b6424b3ff
commit
16ba5deb0e
5 files changed
+221
-7
No files matched your search
@@ -48,6 +48,7 @@ import {
|
||||
updateAgent,
|
||||
} from "@/core/agents/api";
|
||||
import { getStoredAuth } from "@/core/auth";
|
||||
import { useLiveAccount } from "@/core/auth/use-live-account";
|
||||
import { useI18n } from "@/core/i18n/hooks";
|
||||
import { useModels } from "@/core/models/hooks";
|
||||
import { isAgentSkillCandidate, type Skill } from "@/core/skills";
|
||||
@@ -96,6 +97,10 @@ export default function NewAgentPage() {
|
||||
const { skills, isLoading: isSkillsLoading } = useSkills();
|
||||
const { models, isLoading: isModelsLoading } = useModels();
|
||||
|
||||
// 创建请求的归属账号取自「实时」token(apiFetch 每次都重读 localStorage),而非
|
||||
// 本页加载时缓存的身份 —— 用 live 账号提示归属并检测账号是否在会话中途被切换。
|
||||
const live = useLiveAccount();
|
||||
|
||||
// 可配置的技能限定为「内置 + 自己的 + 已发布到广场的」,
|
||||
// 其他用户未发布的自定义技能不可选。
|
||||
const storedAuth = useMemo(() => getStoredAuth(), []);
|
||||
@@ -287,13 +292,37 @@ export default function NewAgentPage() {
|
||||
]);
|
||||
|
||||
const handleSaveAgent = useCallback(async () => {
|
||||
// 新建时归属账号 = 创建请求所用的实时 token 对应账号。若本页加载后登录被切换
|
||||
// (常见于另一标签页登录了别的账号),现在创建会把智能体静默归到新账号名下。
|
||||
// 先弹确认,避免「用 A 账号创建却归到 B 账号」。更新已有智能体不改归属,故跳过。
|
||||
if (!agentId && live.switched) {
|
||||
const ok = window.confirm(
|
||||
`当前登录账号已从「${live.mountDisplayName}」切换为「${live.displayName}」。\n` +
|
||||
`现在创建将把该智能体归属到「${live.displayName}」名下。\n` +
|
||||
`如需归属「${live.mountDisplayName}」,请取消并刷新页面后重新登录。\n\n仍要以「${live.displayName}」创建吗?`,
|
||||
);
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const saved = await ensureAgent();
|
||||
if (!saved) {
|
||||
return;
|
||||
}
|
||||
toast.success(`智能体「${saved.name}」已保存`);
|
||||
toast.success(
|
||||
agentId
|
||||
? `智能体「${saved.name}」已保存`
|
||||
: `智能体「${saved.name}」已创建(归属账号:${live.displayName})`,
|
||||
);
|
||||
router.push("/page/workspace/agents");
|
||||
}, [ensureAgent, router]);
|
||||
}, [
|
||||
agentId,
|
||||
ensureAgent,
|
||||
live.displayName,
|
||||
live.mountDisplayName,
|
||||
live.switched,
|
||||
router,
|
||||
]);
|
||||
|
||||
const handleChatSubmit = useCallback(
|
||||
async (text: string) => {
|
||||
@@ -661,6 +690,25 @@ export default function NewAgentPage() {
|
||||
<p className="text-destructive text-sm">{formError}</p>
|
||||
) : null}
|
||||
|
||||
<div className="rounded-md border px-3 py-2 text-xs dark:border-[#1B477E] dark:bg-[#022248]">
|
||||
<p className="text-muted-foreground">
|
||||
{agentId ? "当前登录账号:" : "创建后归属账号:"}
|
||||
<span className="text-foreground font-medium">
|
||||
「{live.displayName}」
|
||||
</span>
|
||||
</p>
|
||||
{live.switched && (
|
||||
<p className="text-destructive mt-1">
|
||||
⚠ 本页加载时为「{live.mountDisplayName}」,现已切换为「
|
||||
{live.displayName}」。
|
||||
{agentId
|
||||
? "继续保存将以当前账号执行。"
|
||||
: `继续创建将归属「${live.displayName}」。`}
|
||||
建议刷新页面确认账号。
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<Button
|
||||
className="w-full"
|
||||
onClick={() => void handleSaveAgent()}
|
||||
|
||||
Reference in new issue
Block a user