0.4.0 convex及界面修改
This commit is contained in:
@@ -111,7 +111,9 @@ export function FileTree({
|
||||
{rows.map((row, index) => {
|
||||
const label = getFileTreeRowLabel(row);
|
||||
const selected = selectedRowIds.has(row.rowId);
|
||||
const active = row.kind !== "asset" && row.docId === activeId;
|
||||
// 说明:只有“页面本身(doc/index.md)”才需要 active 高亮。
|
||||
// 否则当你打开某个页面时,它下面的思维导图文件夹/附件会出现“灰色假选中”的视觉误导。
|
||||
const active = (row.kind === "doc" || row.kind === "index") && row.docId === activeId;
|
||||
const draggable =
|
||||
row.kind === "doc" || (row.kind === "asset" && isRealFileAsset(row.asset));
|
||||
const inDropFeedback =
|
||||
|
||||
@@ -60,7 +60,7 @@ import {
|
||||
} from "@/lib/file-tree/clipboard";
|
||||
import type { MediaAsset } from "@/types/media";
|
||||
import { AssetContextMenu } from "@/components/sidebar/asset-context-menu";
|
||||
import { ASSETS_CHANGED_EVENT, DOCUMENTS_CHANGED_EVENT, emitAssetsChanged, emitDocumentsChanged } from "@/lib/events";
|
||||
import { ASSETS_CHANGED_EVENT, DOCUMENTS_CHANGED_EVENT, emitAssetsChanged, emitAssetsRestored, emitDocumentsChanged } from "@/lib/events";
|
||||
import { getMnoteRuntimeConfig } from "@/lib/runtime-config";
|
||||
import { DocumentShareDialog } from "@/components/sharing/document-share-dialog";
|
||||
import { api } from "@/lib/convex/api";
|
||||
@@ -239,6 +239,8 @@ function SidebarContent({ initialData, sidebarQuery }: SidebarContentProps) {
|
||||
|
||||
const fileTreeContainerRef = useRef<HTMLDivElement>(null);
|
||||
const creatingDocumentUnderParentRef = useRef<Set<string>>(new Set());
|
||||
// 删除在线表格后,Convex 订阅刷新存在极短延迟;这里做短暂“乐观隐藏”,避免文件树闪回。
|
||||
const hiddenTableIdsRef = useRef<Map<string, number>>(new Map());
|
||||
|
||||
useEffect(() => {
|
||||
setTree(() => {
|
||||
@@ -257,7 +259,14 @@ function SidebarContent({ initialData, sidebarQuery }: SidebarContentProps) {
|
||||
}, [sidebarData.mindmapAssets]);
|
||||
|
||||
useEffect(() => {
|
||||
setTableAssets(sidebarData.tableAssets ?? []);
|
||||
const hidden = hiddenTableIdsRef.current;
|
||||
const now = Date.now();
|
||||
hidden.forEach((ts, id) => {
|
||||
if (now - ts > 15000) {
|
||||
hidden.delete(id);
|
||||
}
|
||||
});
|
||||
setTableAssets((sidebarData.tableAssets ?? []).filter((item) => !hidden.has(item.id)));
|
||||
}, [sidebarData.tableAssets]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -265,8 +274,23 @@ function SidebarContent({ initialData, sidebarQuery }: SidebarContentProps) {
|
||||
}, [activeId, setOpen]);
|
||||
|
||||
useEffect(() => {
|
||||
const onSaved = () => void sidebarQuery.refetch();
|
||||
const onDeleted = () => void sidebarQuery.refetch();
|
||||
const onSaved = (event: Event) => {
|
||||
const detail = (event as CustomEvent<{ tableId?: string }>).detail;
|
||||
const tableId = typeof detail?.tableId === "string" ? detail.tableId : "";
|
||||
if (tableId) {
|
||||
hiddenTableIdsRef.current.delete(tableId);
|
||||
}
|
||||
void sidebarQuery.refetch();
|
||||
};
|
||||
const onDeleted = (event: Event) => {
|
||||
const detail = (event as CustomEvent<{ tableId?: string }>).detail;
|
||||
const tableId = typeof detail?.tableId === "string" ? detail.tableId : "";
|
||||
if (tableId) {
|
||||
hiddenTableIdsRef.current.set(tableId, Date.now());
|
||||
setTableAssets((prev) => prev.filter((item) => item.id !== tableId));
|
||||
}
|
||||
void sidebarQuery.refetch();
|
||||
};
|
||||
window.addEventListener("online-table-saved", onSaved as EventListener);
|
||||
window.addEventListener("online-table-deleted", onDeleted as EventListener);
|
||||
return () => {
|
||||
@@ -288,7 +312,7 @@ function SidebarContent({ initialData, sidebarQuery }: SidebarContentProps) {
|
||||
const msg = e?.message ?? "加载共享摘要失败";
|
||||
if (String(msg).includes("Could not find public function for 'documentShares:listMyShareRoots'")) {
|
||||
setShareSummaryError(
|
||||
"共享功能后端未部署/未更新:请在 `wolai-frontend` 目录执行 `npx convex dev --env-file .env.local` 或 `npx convex deploy --env-file .env.local`。",
|
||||
"共享功能后端未部署/未更新:请在 `wolai-frontend` 目录执行 `npx convex dev --env-file ../.env.all` 或 `npx convex deploy --env-file ../.env.all`。",
|
||||
);
|
||||
} else {
|
||||
setShareSummaryError(msg);
|
||||
@@ -328,7 +352,7 @@ function SidebarContent({ initialData, sidebarQuery }: SidebarContentProps) {
|
||||
} catch (e: any) {
|
||||
const msg = e?.message ?? "加载群组公开摘要失败";
|
||||
if (String(msg).includes("Could not find public function for 'documentGroupShares:listPublicByWorkspace'")) {
|
||||
setGroupPublicError("群组公开功能后端未部署/未更新:请执行 `npx convex dev --env-file .env.local` 或 `npx convex deploy --env-file .env.local`。");
|
||||
setGroupPublicError("群组公开功能后端未部署/未更新:请执行 `npx convex dev --env-file ../.env.all` 或 `npx convex deploy --env-file ../.env.all`。");
|
||||
} else {
|
||||
setGroupPublicError(msg);
|
||||
}
|
||||
@@ -463,13 +487,14 @@ function SidebarContent({ initialData, sidebarQuery }: SidebarContentProps) {
|
||||
const assets = [
|
||||
...(sidebarData.trashedMediaAssets ?? []),
|
||||
...(sidebarData.trashedMindmapAssets ?? []),
|
||||
...(sidebarData.trashedTableAssets ?? []),
|
||||
];
|
||||
const keyword = trashSearch.trim().toLowerCase();
|
||||
if (!keyword) {
|
||||
return assets;
|
||||
}
|
||||
return assets.filter((item) => (item.file_name ?? "未命名附件").toLowerCase().includes(keyword));
|
||||
}, [sidebarData.trashedMediaAssets, sidebarData.trashedMindmapAssets, trashSearch]);
|
||||
}, [sidebarData.trashedMediaAssets, sidebarData.trashedMindmapAssets, sidebarData.trashedTableAssets, trashSearch]);
|
||||
|
||||
const mindmapChildrenSnapshot = useMemo(() => {
|
||||
const mapping = sidebarData.mindmapAssetChildren ?? {};
|
||||
@@ -703,7 +728,7 @@ function SidebarContent({ initialData, sidebarQuery }: SidebarContentProps) {
|
||||
if (officeFileType) {
|
||||
const officeBase = getMnoteRuntimeConfig().onlyofficeBaseUrl;
|
||||
if (!officeBase) {
|
||||
window.alert("缺少 ONLYOFFICE 地址,请在 .env.local 配置 NEXT_PUBLIC_ONLYOFFICE_BASE_URL");
|
||||
window.alert("缺少 ONLYOFFICE 地址,请在 .env.all 配置 NEXT_PUBLIC_ONLYOFFICE_BASE_URL");
|
||||
return;
|
||||
}
|
||||
void (async () => {
|
||||
@@ -1142,15 +1167,19 @@ function SidebarContent({ initialData, sidebarQuery }: SidebarContentProps) {
|
||||
);
|
||||
|
||||
const handleDeleteAssets = useCallback(
|
||||
async (assetIds: string[], assetHint?: MediaAsset) => {
|
||||
async (assetIds: string[], assetHint?: MediaAsset | MediaAsset[]) => {
|
||||
const uniqueAssetIds = Array.from(new Set(assetIds));
|
||||
const assets = uniqueAssetIds
|
||||
.map((id) => mediaAssets.find((item) => item.id === id) ?? mindmapAssets.find((item) => item.id === id) ?? tableAssets.find((item) => item.id === id))
|
||||
.filter(Boolean) as MediaAsset[];
|
||||
|
||||
if (assetHint && !assets.find((item) => item.id === assetHint.id)) {
|
||||
assets.unshift(assetHint);
|
||||
}
|
||||
const hints = Array.isArray(assetHint) ? assetHint : assetHint ? [assetHint] : [];
|
||||
hints.forEach((hint) => {
|
||||
if (!hint) return;
|
||||
if (!assets.find((item) => item.id === hint.id)) {
|
||||
assets.unshift(hint);
|
||||
}
|
||||
});
|
||||
|
||||
const mindmapAssetsToDelete = assets.filter((item) => item.asset_type === "mindmap");
|
||||
const tableAssetsToDelete = assets.filter((item) => item.asset_type === "luckysheet");
|
||||
@@ -1231,16 +1260,32 @@ function SidebarContent({ initialData, sidebarQuery }: SidebarContentProps) {
|
||||
}
|
||||
|
||||
const docText = docIds.length > 0 ? `${docIds.length} 个页面(删除到垃圾桶)` : "";
|
||||
const selectedAssets = assetIds
|
||||
.map((id) => mediaAssets.find((item) => item.id === id) ?? mindmapAssets.find((item) => item.id === id) ?? tableAssets.find((item) => item.id === id))
|
||||
.filter(Boolean) as MediaAsset[];
|
||||
const mindmapCount = selectedAssets.filter((item) => item.asset_type === "mindmap").length;
|
||||
const tableCount = selectedAssets.filter((item) => item.asset_type === "luckysheet").length;
|
||||
const fileCount = selectedAssets.filter((item) => item.asset_type !== "mindmap" && item.asset_type !== "luckysheet").length;
|
||||
|
||||
// 说明:文件树里可能展示“思维导图子文件”等动态资源(不一定在 mindmapAssets 列表里)。
|
||||
// 为避免出现“看起来选中了,但删除不生效”,这里优先从可见行里拿到选中资源的完整元数据。
|
||||
const isAssetRow = (
|
||||
row: FileTreeRow,
|
||||
): row is Extract<FileTreeRow, { kind: "asset" | "asset-folder" }> =>
|
||||
row.kind === "asset" || row.kind === "asset-folder";
|
||||
|
||||
const selectedAssetHints = Array.from(
|
||||
new Map(
|
||||
fileTreeRows
|
||||
.filter((row) => fileTreeSelection.selectedRowIds.has(row.rowId))
|
||||
.filter(isAssetRow)
|
||||
.map((row) => [row.asset.id, row.asset] as const),
|
||||
).values(),
|
||||
);
|
||||
|
||||
const mindmapCount = selectedAssetHints.filter((item) => item.asset_type === "mindmap").length;
|
||||
const tableCount = selectedAssetHints.filter((item) => item.asset_type === "luckysheet").length;
|
||||
const fileCount = selectedAssetHints.filter(
|
||||
(item) => item.asset_type !== "mindmap" && item.asset_type !== "luckysheet",
|
||||
).length;
|
||||
const unknownCount = Math.max(0, assetIds.length - mindmapCount - tableCount - fileCount);
|
||||
const assetTextParts: string[] = [];
|
||||
if (fileCount > 0) assetTextParts.push(`${fileCount} 个附件(删除,10 分钟内可撤销)`);
|
||||
if (mindmapCount > 0) assetTextParts.push(`${mindmapCount} 个思维导图(删除)`);
|
||||
if (mindmapCount > 0) assetTextParts.push(`${mindmapCount} 个思维导图(移入垃圾桶,10 分钟内可恢复)`);
|
||||
if (tableCount > 0) assetTextParts.push(`${tableCount} 个在线表格(删除)`);
|
||||
if (unknownCount > 0) assetTextParts.push(`${unknownCount} 个对象(删除)`);
|
||||
const assetText = assetTextParts.length > 0 ? assetTextParts.join(" + ") : "";
|
||||
@@ -1273,7 +1318,7 @@ function SidebarContent({ initialData, sidebarQuery }: SidebarContentProps) {
|
||||
}
|
||||
|
||||
if (assetIds.length > 0) {
|
||||
await handleDeleteAssets(assetIds);
|
||||
await handleDeleteAssets(assetIds, selectedAssetHints);
|
||||
}
|
||||
|
||||
await refreshTree();
|
||||
@@ -1842,6 +1887,10 @@ function SidebarContent({ initialData, sidebarQuery }: SidebarContentProps) {
|
||||
if (!confirmTrashAction("确认恢复该附件吗?")) {
|
||||
return;
|
||||
}
|
||||
const assetHint =
|
||||
(filteredTrashedMediaAssets ?? []).find((a) => a.id === assetId) ??
|
||||
(sidebarData.trashedMediaAssets ?? []).find((a) => a.id === assetId) ??
|
||||
null;
|
||||
const response = await fetch("/api/media/batch", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
@@ -1853,8 +1902,84 @@ function SidebarContent({ initialData, sidebarQuery }: SidebarContentProps) {
|
||||
return;
|
||||
}
|
||||
await Promise.all([sidebarQuery.refetch(), refreshTree()]);
|
||||
// 重要:删除附件时会同步移除主编辑区块;恢复后向编辑器广播“恢复事件”,由编辑器决定是否插入。
|
||||
let assetForInsert = assetHint as any;
|
||||
if (assetHint?.document_id && String(assetHint.document_id) === String(activeId)) {
|
||||
const fallback = (assetHint.signed_url ?? assetHint.file_url ?? "").trim();
|
||||
let fileUrl = fallback;
|
||||
if (!fileUrl) {
|
||||
try {
|
||||
const res = await fetch(`/api/media/sign?assetId=${encodeURIComponent(assetId)}`);
|
||||
if (res.ok) {
|
||||
const payload = (await res.json().catch(() => null)) as any;
|
||||
fileUrl = String(payload?.signedUrl ?? "").trim();
|
||||
}
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
if (fileUrl) {
|
||||
assetForInsert = {
|
||||
...(assetHint as any),
|
||||
id: assetId,
|
||||
file_url: fileUrl,
|
||||
thumbnail_url: (assetHint.thumbnail_url ?? fileUrl) as any,
|
||||
} as any;
|
||||
editorBridge?.insertMediaAsset?.(assetForInsert);
|
||||
}
|
||||
}
|
||||
if (assetHint?.document_id) {
|
||||
emitAssetsRestored({ docId: String(assetHint.document_id), kind: "media", assetId, asset: assetForInsert });
|
||||
}
|
||||
},
|
||||
[confirmTrashAction, refreshTree, sidebarQuery],
|
||||
[
|
||||
activeId,
|
||||
confirmTrashAction,
|
||||
editorBridge,
|
||||
filteredTrashedMediaAssets,
|
||||
refreshTree,
|
||||
sidebarData.trashedMediaAssets,
|
||||
sidebarQuery,
|
||||
],
|
||||
);
|
||||
|
||||
const handleRestoreTableFromTrash = useCallback(
|
||||
async (tableId: string) => {
|
||||
if (!confirmTrashAction("确认恢复该在线表格吗?")) {
|
||||
return;
|
||||
}
|
||||
const tableHint =
|
||||
(filteredTrashedMediaAssets ?? []).find((a) => a.id === tableId && a.asset_type === "luckysheet") ??
|
||||
(sidebarData.trashedTableAssets ?? []).find((a) => a.id === tableId) ??
|
||||
null;
|
||||
const response = await fetch("/api/tables/restore", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ tableId }),
|
||||
});
|
||||
if (!response.ok) {
|
||||
const payload = await response.json().catch(() => ({}));
|
||||
window.alert(payload?.error ?? "恢复在线表格失败,请稍后再试");
|
||||
return;
|
||||
}
|
||||
await Promise.all([sidebarQuery.refetch(), refreshTree()]);
|
||||
// 重要:删除在线表格会同步移除主编辑区块;恢复后若目标页面正打开,则把表格重新插入主编辑区。
|
||||
if (tableHint?.document_id && String(tableHint.document_id) === String(activeId)) {
|
||||
editorBridge?.insertOnlineTableAsset?.({ documentId: String(tableHint.document_id), tableId });
|
||||
}
|
||||
if (tableHint?.document_id) {
|
||||
emitAssetsRestored({ docId: String(tableHint.document_id), kind: "table", tableId });
|
||||
}
|
||||
},
|
||||
[
|
||||
activeId,
|
||||
confirmTrashAction,
|
||||
editorBridge,
|
||||
filteredTrashedMediaAssets,
|
||||
refreshTree,
|
||||
sidebarData.trashedTableAssets,
|
||||
sidebarQuery,
|
||||
],
|
||||
);
|
||||
|
||||
const handlePurgeMediaAssetFromTrash = useCallback(
|
||||
@@ -1877,6 +2002,26 @@ function SidebarContent({ initialData, sidebarQuery }: SidebarContentProps) {
|
||||
[confirmTrashAction, refreshTree, sidebarQuery],
|
||||
);
|
||||
|
||||
const handlePurgeTableFromTrash = useCallback(
|
||||
async (tableId: string) => {
|
||||
if (!confirmTrashAction("彻底删除后将无法恢复,是否继续?")) {
|
||||
return;
|
||||
}
|
||||
const response = await fetch("/api/tables/purge", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ tableId }),
|
||||
});
|
||||
if (!response.ok) {
|
||||
const payload = await response.json().catch(() => ({}));
|
||||
window.alert(payload?.error ?? "彻底删除在线表格失败,请稍后再试");
|
||||
return;
|
||||
}
|
||||
await Promise.all([sidebarQuery.refetch(), refreshTree()]);
|
||||
},
|
||||
[confirmTrashAction, refreshTree, sidebarQuery],
|
||||
);
|
||||
|
||||
const handleEmptyMediaTrash = useCallback(async () => {
|
||||
if (!sidebarData.activeWorkspaceId) {
|
||||
window.alert("暂无可清空的工作空间");
|
||||
@@ -1887,7 +2032,7 @@ function SidebarContent({ initialData, sidebarQuery }: SidebarContentProps) {
|
||||
}
|
||||
setEmptyingTrash(true);
|
||||
try {
|
||||
const [mediaResp, mindmapResp] = await Promise.all([
|
||||
const [mediaResp, mindmapResp, tableResp] = await Promise.all([
|
||||
fetch("/api/media/empty-trash", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
@@ -1898,6 +2043,11 @@ function SidebarContent({ initialData, sidebarQuery }: SidebarContentProps) {
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ workspaceId: sidebarData.activeWorkspaceId }),
|
||||
}),
|
||||
fetch("/api/tables/empty-trash", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ workspaceId: sidebarData.activeWorkspaceId }),
|
||||
}),
|
||||
]);
|
||||
if (!mediaResp.ok) {
|
||||
const payload = await mediaResp.json().catch(() => ({}));
|
||||
@@ -1909,6 +2059,11 @@ function SidebarContent({ initialData, sidebarQuery }: SidebarContentProps) {
|
||||
window.alert(payload?.error ?? "清空思维导图垃圾桶失败,请稍后再试");
|
||||
return;
|
||||
}
|
||||
if (!tableResp.ok) {
|
||||
const payload = await tableResp.json().catch(() => ({}));
|
||||
window.alert(payload?.error ?? "清空在线表格垃圾桶失败,请稍后再试");
|
||||
return;
|
||||
}
|
||||
await Promise.all([sidebarQuery.refetch(), refreshTree()]);
|
||||
} finally {
|
||||
setEmptyingTrash(false);
|
||||
@@ -1931,8 +2086,15 @@ function SidebarContent({ initialData, sidebarQuery }: SidebarContentProps) {
|
||||
return;
|
||||
}
|
||||
await Promise.all([sidebarQuery.refetch(), refreshTree()]);
|
||||
// 重要:删除思维导图会同步移除主编辑区块;恢复后若目标页面正打开,则把导图重新插入主编辑区。
|
||||
if (documentId && String(documentId) === String(activeId)) {
|
||||
editorBridge?.insertMindmapAsset?.({ documentId, mindmapId });
|
||||
}
|
||||
if (documentId) {
|
||||
emitAssetsRestored({ docId: String(documentId), kind: "mindmap", mindmapId });
|
||||
}
|
||||
},
|
||||
[confirmTrashAction, refreshTree, sidebarQuery],
|
||||
[activeId, confirmTrashAction, editorBridge, refreshTree, sidebarQuery],
|
||||
);
|
||||
|
||||
const handlePurgeMindmapFromTrash = useCallback(
|
||||
@@ -2387,7 +2549,8 @@ function SidebarContent({ initialData, sidebarQuery }: SidebarContentProps) {
|
||||
<span className="text-xs text-gray-400">
|
||||
{sidebarData.trashedDocuments.length +
|
||||
(sidebarData.trashedMediaAssets?.length ?? 0) +
|
||||
(sidebarData.trashedMindmapAssets?.length ?? 0)}{" "}
|
||||
(sidebarData.trashedMindmapAssets?.length ?? 0) +
|
||||
(sidebarData.trashedTableAssets?.length ?? 0)}{" "}
|
||||
条
|
||||
</span>
|
||||
</button>
|
||||
@@ -2509,7 +2672,8 @@ function SidebarContent({ initialData, sidebarQuery }: SidebarContentProps) {
|
||||
/>
|
||||
)}
|
||||
<Drawer open={trashOpen} onOpenChange={setTrashOpen}>
|
||||
<DrawerContent className="max-h-[90vh]">
|
||||
<DrawerContent className="max-h-[90vh] overflow-hidden">
|
||||
<div className="flex max-h-[90vh] flex-col">
|
||||
<DrawerHeader className="text-left">
|
||||
<DrawerTitle>垃圾桶</DrawerTitle>
|
||||
{trashTab === "documents" ? (
|
||||
@@ -2520,6 +2684,7 @@ function SidebarContent({ initialData, sidebarQuery }: SidebarContentProps) {
|
||||
</p>
|
||||
)}
|
||||
</DrawerHeader>
|
||||
<div className="flex-1 overflow-y-auto">
|
||||
<div className="space-y-4 px-4 pb-6">
|
||||
<div className="flex gap-2">
|
||||
<button
|
||||
@@ -2543,7 +2708,9 @@ function SidebarContent({ initialData, sidebarQuery }: SidebarContentProps) {
|
||||
onClick={() => setTrashTab("assets")}
|
||||
>
|
||||
附件 (
|
||||
{(sidebarData.trashedMediaAssets?.length ?? 0) + (sidebarData.trashedMindmapAssets?.length ?? 0)}
|
||||
{(sidebarData.trashedMediaAssets?.length ?? 0) +
|
||||
(sidebarData.trashedMindmapAssets?.length ?? 0) +
|
||||
(sidebarData.trashedTableAssets?.length ?? 0)}
|
||||
)
|
||||
</button>
|
||||
</div>
|
||||
@@ -2624,7 +2791,7 @@ function SidebarContent({ initialData, sidebarQuery }: SidebarContentProps) {
|
||||
删除时间:{item.deleted_at ? new Date(item.deleted_at).toLocaleString() : "-"}
|
||||
</div>
|
||||
<div className="text-xs text-gray-400">
|
||||
类型:{item.mime_type ?? item.asset_type ?? "unknown"}
|
||||
类型:{item.asset_type === "mindmap" ? "思维导图" : (item.mime_type ?? item.asset_type ?? "unknown")}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
@@ -2634,7 +2801,9 @@ function SidebarContent({ initialData, sidebarQuery }: SidebarContentProps) {
|
||||
onClick={() =>
|
||||
void (item.asset_type === "mindmap"
|
||||
? handleRestoreMindmapFromTrash(item.document_id, item.id)
|
||||
: handleRestoreMediaAssetFromTrash(item.id))
|
||||
: item.asset_type === "luckysheet"
|
||||
? handleRestoreTableFromTrash(item.id)
|
||||
: handleRestoreMediaAssetFromTrash(item.id))
|
||||
}
|
||||
>
|
||||
恢复
|
||||
@@ -2645,7 +2814,9 @@ function SidebarContent({ initialData, sidebarQuery }: SidebarContentProps) {
|
||||
onClick={() =>
|
||||
void (item.asset_type === "mindmap"
|
||||
? handlePurgeMindmapFromTrash(item.document_id, item.id)
|
||||
: handlePurgeMediaAssetFromTrash(item.id))
|
||||
: item.asset_type === "luckysheet"
|
||||
? handlePurgeTableFromTrash(item.id)
|
||||
: handlePurgeMediaAssetFromTrash(item.id))
|
||||
}
|
||||
>
|
||||
彻底删除
|
||||
@@ -2656,6 +2827,8 @@ function SidebarContent({ initialData, sidebarQuery }: SidebarContentProps) {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
</>
|
||||
|
||||
@@ -19,6 +19,7 @@ export interface SidebarInitialData {
|
||||
trashedDocuments: TrashRecord[];
|
||||
trashedMediaAssets?: MediaAsset[];
|
||||
trashedMindmapAssets?: MediaAsset[];
|
||||
trashedTableAssets?: MediaAsset[];
|
||||
/**
|
||||
* 在线表格(Luckysheet)在文件树中的“虚拟文件”列表。
|
||||
* 仅用于文件树展示与操作(单击跳转 index / 双击全屏打开 / 同步删除)。
|
||||
|
||||
Reference in New Issue
Block a user