2025-11-23 20:04:29 +08:00
|
|
|
import { DocumentTable, DocumentTableSnapshot, TableRowData, TableSchema } from "@/types/online-table";
|
2025-11-23 17:22:35 +08:00
|
|
|
|
2025-11-23 20:04:29 +08:00
|
|
|
// 默认表格结构:全部为空列,交由用户/全屏自行定义
|
2025-11-23 17:22:35 +08:00
|
|
|
export const DEFAULT_TABLE_SCHEMA: TableSchema = {
|
2025-11-23 20:04:29 +08:00
|
|
|
columns: [],
|
|
|
|
|
frozenRowCount: 0,
|
2025-11-23 17:22:35 +08:00
|
|
|
frozenColCount: 0,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const DEFAULT_TABLE_ROWS = 50;
|
|
|
|
|
export const DEFAULT_TABLE_COLUMNS = 15;
|
|
|
|
|
|
2025-11-29 05:16:23 +08:00
|
|
|
export const createDefaultTableSnapshot = (schema: TableSchema): DocumentTableSnapshot => {
|
|
|
|
|
const frozenRowCount = schema.frozenRowCount ?? 0;
|
|
|
|
|
const frozenColCount = schema.frozenColCount ?? 0;
|
|
|
|
|
return {
|
|
|
|
|
rows: [],
|
|
|
|
|
luckysheet: [
|
|
|
|
|
{
|
|
|
|
|
name: "Sheet1",
|
|
|
|
|
index: 0,
|
|
|
|
|
status: 1,
|
|
|
|
|
order: 0,
|
|
|
|
|
hide: 0,
|
|
|
|
|
row: DEFAULT_TABLE_ROWS,
|
|
|
|
|
column: DEFAULT_TABLE_COLUMNS,
|
|
|
|
|
defaultRowHeight: 19,
|
|
|
|
|
defaultColWidth: 73,
|
|
|
|
|
celldata: [],
|
|
|
|
|
config: {
|
|
|
|
|
columnlen: {},
|
|
|
|
|
rowlen: {},
|
|
|
|
|
},
|
|
|
|
|
frozen: {
|
|
|
|
|
type: frozenRowCount > 0 || frozenColCount > 0 ? "both" : undefined,
|
|
|
|
|
row_focus: frozenRowCount,
|
|
|
|
|
column_focus: frozenColCount,
|
|
|
|
|
},
|
|
|
|
|
scrollLeft: 0,
|
|
|
|
|
scrollTop: 0,
|
|
|
|
|
zoomRatio: 1,
|
|
|
|
|
showGridLines: true,
|
2025-11-23 17:22:35 +08:00
|
|
|
},
|
2025-11-29 05:16:23 +08:00
|
|
|
],
|
|
|
|
|
};
|
|
|
|
|
};
|
2025-11-23 17:22:35 +08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 在 Supabase 中创建一个新的在线表格并返回元数据。
|
|
|
|
|
* @param documentId 当前文档的 ID
|
|
|
|
|
* @param title 表格的初始标题
|
|
|
|
|
* @returns 新创建的 DocumentTable
|
2026-04-13 19:21:42 +08:00
|
|
|
*/
|
|
|
|
|
export async function createOnlineTable(
|
|
|
|
|
documentId: string,
|
|
|
|
|
title: string = "未命名表格"
|
|
|
|
|
): Promise<DocumentTable> {
|
|
|
|
|
// 假设 Next.js API 路由 /api/tables/create 负责与 Supabase 交互
|
|
|
|
|
const response = await fetch("/api/tables/create", {
|
|
|
|
|
method: "POST",
|
|
|
|
|
headers: {
|
|
|
|
|
"Content-Type": "application/json",
|
|
|
|
|
},
|
2025-11-23 17:22:35 +08:00
|
|
|
body: JSON.stringify({
|
|
|
|
|
documentId,
|
|
|
|
|
title,
|
|
|
|
|
schema: DEFAULT_TABLE_SCHEMA,
|
|
|
|
|
snapshot: createDefaultTableSnapshot(DEFAULT_TABLE_SCHEMA),
|
|
|
|
|
}),
|
|
|
|
|
});
|
2026-04-13 19:21:42 +08:00
|
|
|
|
|
|
|
|
if (!response.ok) {
|
|
|
|
|
throw new Error("Failed to create online table.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const newTable: DocumentTable = await response.json();
|
|
|
|
|
return newTable;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取表格元数据 (用于紧凑模式渲染)
|
|
|
|
|
* 实际实现中,这可能需要一个更复杂的获取逻辑,例如同时获取前 N 行数据
|
|
|
|
|
*/
|
2025-11-23 17:22:35 +08:00
|
|
|
export async function getDocumentTable(tableId: string): Promise<DocumentTable> {
|
|
|
|
|
const response = await fetch(`/api/tables/${tableId}`, {
|
|
|
|
|
method: "GET",
|
|
|
|
|
headers: { "Content-Type": "application/json" },
|
|
|
|
|
});
|
2026-04-13 19:21:42 +08:00
|
|
|
|
|
|
|
|
if (!response.ok) {
|
|
|
|
|
throw new Error("Failed to fetch document table.");
|
|
|
|
|
}
|
2025-11-23 17:22:35 +08:00
|
|
|
|
|
|
|
|
return response.json() as Promise<DocumentTable>;
|
|
|
|
|
}
|
2025-11-23 20:04:29 +08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 将表格的 snapshot/行数据回写 Supabase,保持内联与全屏视图一致。
|
|
|
|
|
*/
|
|
|
|
|
export async function saveOnlineTable(
|
|
|
|
|
tableId: string,
|
|
|
|
|
payload: {
|
|
|
|
|
title?: string;
|
|
|
|
|
schema?: TableSchema;
|
|
|
|
|
snapshot?: DocumentTableSnapshot | null;
|
|
|
|
|
rows?: TableRowData[];
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
|
|
viewPreferences?: Record<string, any>;
|
|
|
|
|
},
|
|
|
|
|
): Promise<DocumentTable> {
|
|
|
|
|
const response = await fetch(`/api/tables/${tableId}`, {
|
|
|
|
|
method: "PATCH",
|
|
|
|
|
headers: { "Content-Type": "application/json" },
|
|
|
|
|
body: JSON.stringify(payload),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!response.ok) {
|
|
|
|
|
const message = await response.text().catch(() => "");
|
|
|
|
|
throw new Error(message || "Failed to save online table.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return response.json() as Promise<DocumentTable>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 删除表格及其行数据。
|
|
|
|
|
*/
|
|
|
|
|
export async function deleteOnlineTable(tableId: string): Promise<void> {
|
|
|
|
|
const response = await fetch(`/api/tables/${tableId}`, {
|
|
|
|
|
method: "DELETE",
|
|
|
|
|
headers: { "Content-Type": "application/json" },
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!response.ok) {
|
|
|
|
|
throw new Error("Failed to delete online table.");
|
|
|
|
|
}
|
|
|
|
|
}
|