fix(chat): 发送后切会话不再误标未读,管理端撤回实时同步到对话页

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-17 03:54:58 +08:00
parent 1f4e72550a
commit cda5fad2e5
7 changed files with 476 additions and 41 deletions

View File

@@ -0,0 +1,62 @@
"use client";
import type { ReactNode } from "react";
import { usePostLinkNewTab } from "@/components/PostLinkProvider";
import { linkifyParts } from "@/lib/linkify";
function AutolinkAnchor({
href,
children,
openInNewTab,
}: {
href: string;
children: ReactNode;
openInNewTab: boolean;
}) {
return (
<a
href={href}
className="j13-autolink break-all"
style={{ color: "var(--accent)", textDecoration: "underline" }}
{...(openInNewTab ? { target: "_blank", rel: "noopener noreferrer" } : {})}
onClick={(e) => e.stopPropagation()}
onContextMenu={(e) => e.stopPropagation()}
>
{children}
</a>
);
}
/**
* 纯文本自动识别 URL。
* forceNewTab:聊天等场景始终新开;否则读 PostLinkProvider(post_link_new_tab)。
*/
export default function AutolinkText({
text,
renderText,
forceNewTab = false,
}: {
text: string;
renderText?: (segment: string) => ReactNode;
forceNewTab?: boolean;
}) {
const settingNewTab = usePostLinkNewTab();
const openInNewTab = forceNewTab || settingNewTab;
const parts = linkifyParts(text);
return (
<>
{parts.map((p, i) => {
const key = `l-${i}`;
if (p.type === "url") {
return (
<AutolinkAnchor key={key} href={p.href} openInNewTab={openInNewTab}>
{p.value}
</AutolinkAnchor>
);
}
if (renderText) return <span key={key}>{renderText(p.value)}</span>;
return <span key={key}>{p.value}</span>;
})}
</>
);
}

View File

@@ -0,0 +1,20 @@
"use client";
import { createContext, useContext } from "react";
const PostLinkCtx = createContext(true);
/** 帖内 Markdown 外链是否新标签打开(来自公开站点设置) */
export default function PostLinkProvider({
openInNewTab,
children,
}: {
openInNewTab: boolean;
children: React.ReactNode;
}) {
return <PostLinkCtx.Provider value={openInNewTab}>{children}</PostLinkCtx.Provider>;
}
export function usePostLinkNewTab() {
return useContext(PostLinkCtx);
}