0.2.1 onlyoffice修复
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
import { mutation, query } from "./_generated/server";
|
||||
import { v } from "convex/values";
|
||||
import { nowIso } from "./_utils/time";
|
||||
import type { MutationCtx, QueryCtx } from "./_generated/server";
|
||||
|
||||
type WorkspaceSummary = {
|
||||
id: string;
|
||||
name: string;
|
||||
type: "personal" | "team";
|
||||
iconUrl: string | null;
|
||||
memberCount: number;
|
||||
isDefault: boolean;
|
||||
};
|
||||
|
||||
async function findWorkspaceById(ctx: QueryCtx | MutationCtx, workspaceId: string) {
|
||||
return await ctx.db
|
||||
.query("workspaces")
|
||||
.withIndex("by_workspace_id", (q) => q.eq("id", workspaceId))
|
||||
.first();
|
||||
}
|
||||
|
||||
async function countMembers(ctx: QueryCtx | MutationCtx, workspaceId: string): Promise<number> {
|
||||
const members = await ctx.db
|
||||
.query("workspace_members")
|
||||
.withIndex("by_workspace_id", (q) => q.eq("workspace_id", workspaceId))
|
||||
.collect();
|
||||
return members.length;
|
||||
}
|
||||
|
||||
export const ensureDefaultWorkspace = mutation({
|
||||
args: {
|
||||
userId: v.string(),
|
||||
fallbackName: v.optional(v.string()),
|
||||
workspaceIdIfCreate: v.string(),
|
||||
},
|
||||
handler: async (ctx, args) => {
|
||||
const memberships = await ctx.db
|
||||
.query("workspace_members")
|
||||
.withIndex("by_user_id", (q) => q.eq("user_id", args.userId))
|
||||
.collect();
|
||||
|
||||
if (memberships.length === 0) {
|
||||
const workspaceName = (args.fallbackName ?? "").trim()
|
||||
? `${args.fallbackName!.trim()} 的空间`
|
||||
: "我的空间";
|
||||
|
||||
const ts = nowIso();
|
||||
await ctx.db.insert("workspaces", {
|
||||
id: args.workspaceIdIfCreate,
|
||||
name: workspaceName,
|
||||
type: "personal",
|
||||
icon_url: null,
|
||||
created_by: args.userId,
|
||||
created_at: ts,
|
||||
});
|
||||
|
||||
await ctx.db.insert("workspace_members", {
|
||||
workspace_id: args.workspaceIdIfCreate,
|
||||
user_id: args.userId,
|
||||
role: "owner",
|
||||
is_default: true,
|
||||
created_at: ts,
|
||||
});
|
||||
|
||||
const summary: WorkspaceSummary = {
|
||||
id: args.workspaceIdIfCreate,
|
||||
name: workspaceName,
|
||||
type: "personal",
|
||||
iconUrl: null,
|
||||
memberCount: 1,
|
||||
isDefault: true,
|
||||
};
|
||||
|
||||
return {
|
||||
workspaces: [summary],
|
||||
activeWorkspaceId: args.workspaceIdIfCreate,
|
||||
};
|
||||
}
|
||||
|
||||
// 有 membership 就认为已有 workspace;再兜底一次补齐 workspace 记录。
|
||||
const workspaceIds = Array.from(new Set(memberships.map((m) => m.workspace_id)));
|
||||
const summaries: WorkspaceSummary[] = [];
|
||||
for (const wid of workspaceIds) {
|
||||
const ws = await findWorkspaceById(ctx, wid);
|
||||
if (!ws) continue;
|
||||
const memberCount = await countMembers(ctx, wid);
|
||||
const isDefault = memberships.some((m) => m.workspace_id === wid && m.is_default);
|
||||
summaries.push({
|
||||
id: ws.id,
|
||||
name: ws.name,
|
||||
type: ws.type,
|
||||
iconUrl: ws.icon_url,
|
||||
memberCount: memberCount || 1,
|
||||
isDefault,
|
||||
});
|
||||
}
|
||||
|
||||
// 说明:保持与原 fetchWorkspaceSummaries 一致:默认 workspace 优先,否则取第一个。
|
||||
const defaultWs = summaries.find((w) => w.isDefault);
|
||||
const activeWorkspaceId = defaultWs?.id ?? summaries[0]?.id ?? "";
|
||||
return { workspaces: summaries, activeWorkspaceId };
|
||||
},
|
||||
});
|
||||
|
||||
export const fetchWorkspaceSummaries = query({
|
||||
args: { userId: v.string() },
|
||||
handler: async (ctx, args) => {
|
||||
// 说明:为了复用 ensureDefaultWorkspace 的返回结构,这里直接走同样的聚合逻辑。
|
||||
const memberships = await ctx.db
|
||||
.query("workspace_members")
|
||||
.withIndex("by_user_id", (q) => q.eq("user_id", args.userId))
|
||||
.collect();
|
||||
|
||||
const workspaceIds = Array.from(new Set(memberships.map((m) => m.workspace_id)));
|
||||
const summaries: WorkspaceSummary[] = [];
|
||||
for (const wid of workspaceIds) {
|
||||
const ws = await findWorkspaceById(ctx, wid);
|
||||
if (!ws) continue;
|
||||
const memberCount = await countMembers(ctx, wid);
|
||||
const isDefault = memberships.some((m) => m.workspace_id === wid && m.is_default);
|
||||
summaries.push({
|
||||
id: ws.id,
|
||||
name: ws.name,
|
||||
type: ws.type,
|
||||
iconUrl: ws.icon_url,
|
||||
memberCount: memberCount || 1,
|
||||
isDefault,
|
||||
});
|
||||
}
|
||||
|
||||
const defaultWs = summaries.find((w) => w.isDefault);
|
||||
const activeWorkspaceId = defaultWs?.id ?? summaries[0]?.id ?? "";
|
||||
return { workspaces: summaries, activeWorkspaceId };
|
||||
},
|
||||
});
|
||||
|
||||
export const switchDefaultWorkspace = mutation({
|
||||
args: { userId: v.string(), workspaceId: v.string() },
|
||||
handler: async (ctx, args) => {
|
||||
const target = await ctx.db
|
||||
.query("workspace_members")
|
||||
.withIndex("by_workspace_user", (q) =>
|
||||
q.eq("workspace_id", args.workspaceId).eq("user_id", args.userId),
|
||||
)
|
||||
.first();
|
||||
|
||||
if (!target) {
|
||||
throw new Error("无权切换至该工作空间");
|
||||
}
|
||||
|
||||
const memberships = await ctx.db
|
||||
.query("workspace_members")
|
||||
.withIndex("by_user_id", (q) => q.eq("user_id", args.userId))
|
||||
.collect();
|
||||
|
||||
// 说明:Convex 暂无批量 update,这里逐条 patch。
|
||||
for (const m of memberships) {
|
||||
if (m.is_default) {
|
||||
await ctx.db.patch(m._id, { is_default: false });
|
||||
}
|
||||
}
|
||||
|
||||
await ctx.db.patch(target._id, { is_default: true });
|
||||
return { ok: true };
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user