Stop shipping hard-coded demo docs/projects into production builds, drop local mock items on authoritative empty server lists, and purge stale demo seed residue from localStorage on boot. Co-authored-by: Cursor <cursoragent@cursor.com>
74 lines
2.2 KiB
TypeScript
74 lines
2.2 KiB
TypeScript
import { Project } from '../types/projectWorkflow';
|
|
import { ProjectInfo, ProjectMember } from '../types/workbench';
|
|
import { isDemoSeedProjectId } from '../data/demoSeedIds';
|
|
|
|
type UserCatalogEntry = { id: number; name: string };
|
|
|
|
export function resolveUserDisplayName(
|
|
userId: number,
|
|
catalog: UserCatalogEntry[],
|
|
fallback = '未知用户'
|
|
): string {
|
|
return catalog.find((u) => u.id === userId)?.name ?? fallback;
|
|
}
|
|
|
|
export function mapServerProjectToProjectInfo(
|
|
project: Project,
|
|
catalog: UserCatalogEntry[],
|
|
existing?: ProjectInfo
|
|
): ProjectInfo {
|
|
const creatorName = resolveUserDisplayName(project.creator_user_id, catalog);
|
|
const defaultMember: ProjectMember = {
|
|
userId: project.creator_user_id,
|
|
userName: creatorName,
|
|
role: 'creator',
|
|
status: 'active',
|
|
joinedAt: project.created_at,
|
|
};
|
|
|
|
return {
|
|
id: project.id,
|
|
title: project.name,
|
|
deviceType: project.device_type || existing?.deviceType || '',
|
|
description: project.intended_use || existing?.description || '',
|
|
creatorId: project.creator_user_id,
|
|
creatorName,
|
|
createdAt: project.created_at,
|
|
members: existing?.members?.length ? existing.members : [defaultMember],
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 服务端项目覆盖同 id 本地项。
|
|
* 默认丢弃 local-only 的 demo seed 项目,避免侧边栏幻影演示项。
|
|
*/
|
|
export function mergeProjectLists(
|
|
local: ProjectInfo[],
|
|
fromServer: ProjectInfo[],
|
|
opts?: { dropLocalOnlyDemoSeeds?: boolean },
|
|
): ProjectInfo[] {
|
|
const dropLocalOnlyDemo = opts?.dropLocalOnlyDemoSeeds !== false;
|
|
const byId = new Map<number, ProjectInfo>();
|
|
const serverIds = new Set(fromServer.map((p) => p.id));
|
|
|
|
for (const project of local) {
|
|
if (dropLocalOnlyDemo && isDemoSeedProjectId(project.id) && !serverIds.has(project.id)) {
|
|
continue;
|
|
}
|
|
byId.set(project.id, project);
|
|
}
|
|
for (const project of fromServer) {
|
|
const previous = byId.get(project.id);
|
|
if (!previous) {
|
|
byId.set(project.id, project);
|
|
continue;
|
|
}
|
|
byId.set(project.id, {
|
|
...previous,
|
|
...project,
|
|
members: previous.members.length > 0 ? previous.members : project.members,
|
|
});
|
|
}
|
|
return [...byId.values()];
|
|
}
|