Files
Agent-System/web/src/lib/projectMemberAdapter.ts
T
weichenandCursor c1bdfe3920 feat(web): persist exclusive reviewer duty on project create
Keep project_role as member/viewer, send document_duty=reviewer for USER_B, and clear the seed 李主管 reviewer so the assigned reviewer is the one that syncs.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-13 21:57:53 +00:00

62 lines
1.9 KiB
TypeScript

import { ApiProjectMemberRecord, ApiProjectMemberRole } from '../api/projectMembers';
import { ProjectMember, ProjectMemberRole } from '../types/workbench';
import { memberRoleFromDocumentDuty } from './projectDocumentDuty';
/** UI 角色 → 服务端 project_role(禁止 author/reviewer/approver)。 */
export function toApiProjectRole(
role: ProjectMemberRole,
userId: number,
creatorId: number
): ApiProjectMemberRole {
if (role === 'creator' || role === 'owner' || (userId === creatorId && role !== 'viewer')) {
return 'owner';
}
if (role === 'viewer') {
return 'viewer';
}
return 'member';
}
/** 服务端 project_role → UI 角色。 */
export function fromApiProjectRole(
apiRole: string,
userId: number,
creatorId: number
): ProjectMemberRole {
const normalized = apiRole.trim().toLowerCase();
if (normalized === 'owner') {
return userId === creatorId ? 'creator' : 'owner';
}
if (normalized === 'viewer') {
return 'viewer';
}
return 'member';
}
export function mapApiMemberToProjectMember(
rec: ApiProjectMemberRecord,
creatorId: number
): ProjectMember {
return {
userId: rec.user_id,
userName: rec.name?.trim() || rec.username?.trim() || `用户 #${rec.user_id}`,
role: memberRoleFromDocumentDuty(
rec.document_duty,
fromApiProjectRole(rec.project_role, rec.user_id, creatorId),
),
status: rec.status === 'exited' ? 'exited' : 'active',
joinedAt: rec.joined_at || new Date().toLocaleString(),
exitedAt: rec.status === 'exited' ? rec.joined_at : undefined,
};
}
export function mapApiMembersToProjectMembers(
records: ApiProjectMemberRecord[],
creatorId: number
): ProjectMember[] {
return records.map((rec) => mapApiMemberToProjectMember(rec, creatorId));
}
/** 项目成员管理可选角色(与后端校验一致)。 */
export const ASSIGNABLE_PROJECT_MEMBER_ROLES: ProjectMemberRole[] = ['member', 'viewer'];