Create Feishu sheets for spreadsheet files

This commit is contained in:
wuyang6
2026-05-11 17:56:58 +08:00
parent dba827b9b0
commit 3a4da782ec
4 changed files with 410 additions and 23 deletions
@@ -223,6 +223,7 @@ type SessionFile = {
download_url: string;
online_doc_url?: string | null;
online_doc_title?: string | null;
online_doc_kind?: string | null;
online_doc_updated_at?: number | null;
};
@@ -392,10 +393,14 @@ function SessionFileRow({ file }: { file: SessionFile }) {
status: "idle" | "loading" | "auth" | "done" | "error";
message?: string;
url?: string | null;
kind?: string | null;
}>({
status: file.online_doc_url ? "done" : "idle",
message: file.online_doc_url ? "已转在线文档" : undefined,
message: file.online_doc_url
? `已转${onlineFileKindLabel(file.online_doc_kind, file.name)}`
: undefined,
url: file.online_doc_url ?? null,
kind: file.online_doc_kind ?? null,
});
const canCreateOnlineDoc = isOnlineDocSupported(file.name);
const onlineDocUrl = onlineDoc.url ?? file.online_doc_url ?? null;
@@ -406,7 +411,7 @@ function SessionFileRow({ file }: { file: SessionFile }) {
try {
pendingWindow = window.open("about:blank", "_blank");
if (pendingWindow) {
pendingWindow.document.write("正在创建飞书在线文...");
pendingWindow.document.write("正在创建飞书在线文...");
}
} catch {
pendingWindow = null;
@@ -472,6 +477,7 @@ function SessionFileRow({ file }: { file: SessionFile }) {
return;
}
const url = typeof payload.url === "string" ? payload.url : null;
const kind = typeof payload.kind === "string" ? payload.kind : null;
if (url) {
if (pendingWindow) {
try {
@@ -488,8 +494,11 @@ function SessionFileRow({ file }: { file: SessionFile }) {
}
setOnlineDoc({
status: "done",
message: url ? "已生成在线文档" : "已生成",
message: url
? `已生成${onlineFileKindLabel(kind, file.name)}`
: "已生成",
url,
kind,
});
window.dispatchEvent(new CustomEvent("claw-session-files-changed"));
} catch (error) {
@@ -513,7 +522,7 @@ function SessionFileRow({ file }: { file: SessionFile }) {
target="_blank"
rel="noreferrer"
className="block truncate font-medium text-primary text-sm underline-offset-4 hover:underline"
title={`${file.name} · 打开在线文档`}
title={`${file.name} · 打开${onlineFileKindLabel(onlineDoc.kind ?? file.online_doc_kind, file.name)}`}
>
{file.name}
</a>
@@ -561,8 +570,8 @@ function SessionFileRow({ file }: { file: SessionFile }) {
<button
type="button"
className="flex size-8 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50"
aria-label={`${file.name} 转为在线文`}
title="转为在线文"
aria-label={`${file.name} 转为飞书在线文`}
title="转为飞书在线文"
disabled={onlineDoc.status === "loading"}
onClick={createOnlineDoc}
>
@@ -590,6 +599,18 @@ function isOnlineDocSupported(fileName: string) {
);
}
function onlineFileKindLabel(
kind: string | null | undefined,
fileName: string,
) {
const normalized = kind?.toLowerCase();
if (normalized === "sheet") return "在线表格";
if (["csv", "xlsx"].includes(fileExtension(fileName).toLowerCase())) {
return "在线表格";
}
return "在线文档";
}
function extractErrorMessage(payload: Record<string, unknown>) {
const detail = payload.detail;
if (typeof detail === "string") return detail;