245 lines
8.1 KiB
TypeScript
245 lines
8.1 KiB
TypeScript
import { normalizeNullableStringId, normalizeStringId } from './shared';
|
|
|
|
type ProjectStatusCode = Api.Project.ProjectStatusCode;
|
|
type ProjectStatusActionCode = Exclude<Api.Project.ProjectStatusActionCode, 'auto_start'>;
|
|
|
|
type StringIdResponse = string | number;
|
|
|
|
export type ProjectLocalDateValue = string | number[] | null;
|
|
|
|
export type LifecycleActionResponse<ActionCode extends string> = Partial<Api.Project.LifecycleAction<ActionCode>> & {
|
|
actionCode: ActionCode;
|
|
};
|
|
|
|
export type ProjectExecutionResponse = Omit<
|
|
Api.Project.ProjectExecution,
|
|
| 'id'
|
|
| 'projectId'
|
|
| 'projectRequirementId'
|
|
| 'ownerId'
|
|
| 'availableActions'
|
|
| 'plannedStartDate'
|
|
| 'plannedEndDate'
|
|
| 'actualStartDate'
|
|
| 'actualEndDate'
|
|
| 'progressRate'
|
|
> & {
|
|
id: StringIdResponse;
|
|
projectId: StringIdResponse;
|
|
projectRequirementId?: StringIdResponse | null;
|
|
ownerId: StringIdResponse;
|
|
availableActions?: LifecycleActionResponse<Api.Project.ProjectExecutionActionCode>[] | null;
|
|
plannedStartDate?: ProjectLocalDateValue;
|
|
plannedEndDate?: ProjectLocalDateValue;
|
|
actualStartDate?: ProjectLocalDateValue;
|
|
actualEndDate?: ProjectLocalDateValue;
|
|
progressRate?: number | null;
|
|
};
|
|
|
|
export type ExecutionMemberResponse = Omit<Api.Project.ExecutionMember, 'id' | 'executionId' | 'userId'> & {
|
|
id: StringIdResponse;
|
|
executionId: StringIdResponse;
|
|
userId: StringIdResponse;
|
|
};
|
|
|
|
export type ExecutionMemberLogResponse = Omit<
|
|
Api.Project.ExecutionMemberLog,
|
|
'id' | 'executionId' | 'userId' | 'operatorUserId'
|
|
> & {
|
|
id: StringIdResponse;
|
|
executionId: StringIdResponse;
|
|
userId: StringIdResponse;
|
|
operatorUserId: StringIdResponse;
|
|
};
|
|
|
|
export type ProjectTaskResponse = Omit<
|
|
Api.Project.ProjectTask,
|
|
| 'id'
|
|
| 'projectId'
|
|
| 'executionId'
|
|
| 'parentTaskId'
|
|
| 'ownerId'
|
|
| 'availableActions'
|
|
| 'plannedStartDate'
|
|
| 'plannedEndDate'
|
|
| 'actualStartDate'
|
|
| 'actualEndDate'
|
|
| 'progressRate'
|
|
> & {
|
|
id: StringIdResponse;
|
|
projectId: StringIdResponse;
|
|
executionId: StringIdResponse;
|
|
parentTaskId?: StringIdResponse | null;
|
|
ownerId: StringIdResponse;
|
|
availableActions?: LifecycleActionResponse<Api.Project.ProjectTaskActionCode>[] | null;
|
|
plannedStartDate?: ProjectLocalDateValue;
|
|
plannedEndDate?: ProjectLocalDateValue;
|
|
actualStartDate?: ProjectLocalDateValue;
|
|
actualEndDate?: ProjectLocalDateValue;
|
|
progressRate?: number | null;
|
|
};
|
|
|
|
export interface ProjectMemberResponse {
|
|
id: string | number;
|
|
userId: string | number;
|
|
userNickname: string;
|
|
roleId: string | number;
|
|
roleName: string;
|
|
roleCode: string;
|
|
managerFlag: boolean;
|
|
status: 0 | 1;
|
|
joinedTime: string;
|
|
leftTime?: string | null;
|
|
remark?: string | null;
|
|
}
|
|
|
|
const projectLifecycleActionNameMap: Record<ProjectStatusActionCode, string> = {
|
|
pause: '暂停项目',
|
|
resume: '恢复项目',
|
|
complete: '完成项目',
|
|
cancel: '取消项目',
|
|
reopen: '重新开启',
|
|
archive: '归档项目'
|
|
};
|
|
|
|
const projectLifecycleActionReasonRequiredMap: Record<ProjectStatusActionCode, boolean> = {
|
|
pause: true,
|
|
resume: false,
|
|
complete: true,
|
|
cancel: true,
|
|
reopen: true,
|
|
archive: false
|
|
};
|
|
|
|
const projectLifecycleActionMap: Record<ProjectStatusCode, ProjectStatusActionCode[]> = {
|
|
pending: ['cancel'],
|
|
active: ['pause', 'complete', 'cancel'],
|
|
paused: ['resume', 'cancel'],
|
|
completed: ['reopen', 'archive'],
|
|
cancelled: [],
|
|
archived: []
|
|
};
|
|
|
|
export function getProjectLifecycleActions(statusCode: ProjectStatusCode): Api.Project.ProjectLifecycleAction[] {
|
|
return projectLifecycleActionMap[statusCode].map(actionCode => ({
|
|
actionCode,
|
|
actionName: projectLifecycleActionNameMap[actionCode],
|
|
needReason: projectLifecycleActionReasonRequiredMap[actionCode]
|
|
}));
|
|
}
|
|
|
|
export function normalizeProjectLocalDate(value: ProjectLocalDateValue | undefined) {
|
|
if (value === null || value === undefined || value === '') {
|
|
return null;
|
|
}
|
|
|
|
if (Array.isArray(value)) {
|
|
const [year, month, day] = value;
|
|
|
|
if (!year || !month || !day) {
|
|
return null;
|
|
}
|
|
|
|
return [year, month, day].map(item => String(item).padStart(2, '0')).join('-');
|
|
}
|
|
|
|
return String(value);
|
|
}
|
|
|
|
export function normalizeLifecycleActions<ActionCode extends string>(
|
|
actions: LifecycleActionResponse<ActionCode>[] | null | undefined
|
|
): Api.Project.LifecycleAction<ActionCode>[] {
|
|
return (actions ?? []).map(action => ({
|
|
actionCode: action.actionCode,
|
|
actionName: action.actionName ?? '',
|
|
needReason: Boolean(action.needReason)
|
|
}));
|
|
}
|
|
|
|
export function normalizeProjectMember(response: ProjectMemberResponse): Api.Project.ProjectMember {
|
|
return {
|
|
id: normalizeStringId(response.id),
|
|
userId: normalizeStringId(response.userId),
|
|
userNickname: response.userNickname || '',
|
|
roleId: normalizeStringId(response.roleId),
|
|
roleName: response.roleName || '',
|
|
roleCode: response.roleCode || '',
|
|
managerFlag: Boolean(response.managerFlag),
|
|
status: response.status,
|
|
joinedTime: response.joinedTime,
|
|
leftTime: response.leftTime ?? null,
|
|
remark: response.remark ?? null
|
|
};
|
|
}
|
|
|
|
export function normalizeProjectExecution(response: ProjectExecutionResponse): Api.Project.ProjectExecution {
|
|
return {
|
|
...response,
|
|
id: normalizeStringId(response.id),
|
|
projectId: normalizeStringId(response.projectId),
|
|
projectRequirementId: normalizeNullableStringId(response.projectRequirementId),
|
|
ownerId: normalizeStringId(response.ownerId),
|
|
ownerNickname: response.ownerNickname ?? null,
|
|
statusName: response.statusName ?? null,
|
|
terminal: Boolean(response.terminal),
|
|
allowEdit: Boolean(response.allowEdit),
|
|
availableActions: normalizeLifecycleActions(response.availableActions),
|
|
plannedStartDate: normalizeProjectLocalDate(response.plannedStartDate),
|
|
plannedEndDate: normalizeProjectLocalDate(response.plannedEndDate),
|
|
actualStartDate: normalizeProjectLocalDate(response.actualStartDate),
|
|
actualEndDate: normalizeProjectLocalDate(response.actualEndDate),
|
|
progressRate: typeof response.progressRate === 'number' ? response.progressRate : 0,
|
|
executionDesc: response.executionDesc ?? null,
|
|
lastStatusReason: response.lastStatusReason ?? null
|
|
};
|
|
}
|
|
|
|
export function normalizeExecutionMember(response: ExecutionMemberResponse): Api.Project.ExecutionMember {
|
|
return {
|
|
...response,
|
|
id: normalizeStringId(response.id),
|
|
executionId: normalizeStringId(response.executionId),
|
|
userId: normalizeStringId(response.userId),
|
|
userNickname: response.userNickname ?? null,
|
|
joinedAt: response.joinedAt ?? null,
|
|
removedAt: response.removedAt ?? null,
|
|
removedReason: response.removedReason ?? null
|
|
};
|
|
}
|
|
|
|
export function normalizeExecutionMemberLog(response: ExecutionMemberLogResponse): Api.Project.ExecutionMemberLog {
|
|
return {
|
|
...response,
|
|
id: normalizeStringId(response.id),
|
|
executionId: normalizeStringId(response.executionId),
|
|
userId: normalizeStringId(response.userId),
|
|
operatorUserId: normalizeStringId(response.operatorUserId),
|
|
userNicknameSnapshot: response.userNicknameSnapshot ?? null,
|
|
operatorNicknameSnapshot: response.operatorNicknameSnapshot ?? null,
|
|
reason: response.reason ?? null
|
|
};
|
|
}
|
|
|
|
export function normalizeProjectTask(response: ProjectTaskResponse): Api.Project.ProjectTask {
|
|
return {
|
|
...response,
|
|
id: normalizeStringId(response.id),
|
|
projectId: normalizeStringId(response.projectId),
|
|
executionId: normalizeStringId(response.executionId),
|
|
parentTaskId: normalizeNullableStringId(response.parentTaskId),
|
|
ownerId: normalizeStringId(response.ownerId),
|
|
ownerNickname: response.ownerNickname ?? null,
|
|
statusName: response.statusName ?? null,
|
|
terminal: Boolean(response.terminal),
|
|
allowEdit: Boolean(response.allowEdit),
|
|
availableActions: normalizeLifecycleActions(response.availableActions),
|
|
progressRate: typeof response.progressRate === 'number' ? response.progressRate : 0,
|
|
plannedStartDate: normalizeProjectLocalDate(response.plannedStartDate),
|
|
plannedEndDate: normalizeProjectLocalDate(response.plannedEndDate),
|
|
actualStartDate: normalizeProjectLocalDate(response.actualStartDate),
|
|
actualEndDate: normalizeProjectLocalDate(response.actualEndDate),
|
|
taskDesc: response.taskDesc ?? null,
|
|
lastStatusReason: response.lastStatusReason ?? null
|
|
};
|
|
}
|