2026-05-09 11:30:34 +08:00
|
|
|
|
import { WEB_SERVICE_PREFIX } from '@/constants/service';
|
|
|
|
|
|
import { request } from '../request';
|
|
|
|
|
|
import {
|
|
|
|
|
|
type ServiceRequestResult,
|
|
|
|
|
|
mapServiceResult,
|
|
|
|
|
|
normalizeNullableStringId,
|
|
|
|
|
|
normalizeStringId,
|
|
|
|
|
|
safeJsonRequestConfig
|
|
|
|
|
|
} from './shared';
|
|
|
|
|
|
import {
|
2026-05-12 21:41:39 +08:00
|
|
|
|
type ExecutionAssigneeLogResponse,
|
|
|
|
|
|
type ExecutionAssigneeResponse,
|
2026-06-04 11:26:51 +08:00
|
|
|
|
type MyExecutionResponse,
|
|
|
|
|
|
type MyOwnedProjectResponse,
|
|
|
|
|
|
type MyParticipatedProjectResponse,
|
2026-05-09 11:30:34 +08:00
|
|
|
|
type ProjectExecutionResponse,
|
|
|
|
|
|
type ProjectLocalDateValue,
|
|
|
|
|
|
type ProjectMemberResponse,
|
|
|
|
|
|
type ProjectTaskResponse,
|
2026-05-12 21:41:39 +08:00
|
|
|
|
type TaskAssigneeFromApiResponse,
|
|
|
|
|
|
type TaskAssigneeLogResponse,
|
|
|
|
|
|
type TaskWorklogResponse,
|
2026-05-09 11:30:34 +08:00
|
|
|
|
getProjectLifecycleActions,
|
2026-05-12 21:41:39 +08:00
|
|
|
|
normalizeExecutionAssignee,
|
|
|
|
|
|
normalizeExecutionAssigneeLog,
|
2026-06-04 11:26:51 +08:00
|
|
|
|
normalizeMyExecution,
|
|
|
|
|
|
normalizeMyOwnedProject,
|
|
|
|
|
|
normalizeMyParticipatedProject,
|
2026-05-09 11:30:34 +08:00
|
|
|
|
normalizeProjectExecution,
|
|
|
|
|
|
normalizeProjectLocalDate,
|
|
|
|
|
|
normalizeProjectMember,
|
2026-05-12 21:41:39 +08:00
|
|
|
|
normalizeProjectTask,
|
|
|
|
|
|
normalizeTaskAssignee,
|
|
|
|
|
|
normalizeTaskAssigneeLog,
|
|
|
|
|
|
normalizeTaskWorklog
|
2026-05-09 11:30:34 +08:00
|
|
|
|
} from './project-shared';
|
|
|
|
|
|
|
|
|
|
|
|
const PROJECT_PREFIX = `${WEB_SERVICE_PREFIX}/project/project`;
|
|
|
|
|
|
|
2026-06-11 14:02:26 +08:00
|
|
|
|
export type ProjectResponse = Omit<
|
2026-05-09 11:30:34 +08:00
|
|
|
|
Api.Project.Project,
|
|
|
|
|
|
'id' | 'managerUserId' | 'productId' | 'plannedStartDate' | 'plannedEndDate' | 'actualStartDate' | 'actualEndDate'
|
|
|
|
|
|
> & {
|
|
|
|
|
|
id: string | number;
|
|
|
|
|
|
managerUserId?: string | number | null;
|
|
|
|
|
|
productId?: string | number | null;
|
|
|
|
|
|
plannedStartDate?: ProjectLocalDateValue;
|
|
|
|
|
|
plannedEndDate?: ProjectLocalDateValue;
|
|
|
|
|
|
actualStartDate?: ProjectLocalDateValue;
|
|
|
|
|
|
actualEndDate?: ProjectLocalDateValue;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
type ProjectPageResponse = Api.Project.PageResult<ProjectResponse>;
|
|
|
|
|
|
type ProjectExecutionPageResponse = Api.Project.PageResult<ProjectExecutionResponse>;
|
|
|
|
|
|
type ProjectTaskPageResponse = Api.Project.PageResult<ProjectTaskResponse>;
|
|
|
|
|
|
type StatusBoardResponse = Api.Project.StatusBoard;
|
2026-05-14 09:05:08 +08:00
|
|
|
|
type ProjectTaskBoardPageResponse = {
|
|
|
|
|
|
items: Array<{
|
|
|
|
|
|
statusCode: string;
|
|
|
|
|
|
statusName: string;
|
|
|
|
|
|
sort: number;
|
|
|
|
|
|
terminal?: boolean;
|
|
|
|
|
|
list: ProjectTaskResponse[];
|
|
|
|
|
|
total: number;
|
|
|
|
|
|
}>;
|
|
|
|
|
|
};
|
2026-05-09 11:30:34 +08:00
|
|
|
|
|
|
|
|
|
|
type ProjectContextResponse = Omit<Api.Project.ProjectContext, 'currentProject' | 'navs'> & {
|
|
|
|
|
|
currentProject: Omit<Api.Project.ProjectContext['currentProject'], 'id'> & { id: string | number };
|
|
|
|
|
|
navs: Array<Omit<Api.Project.ProjectContext['navs'][number], 'id'> & { id: string | number }>;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
function getExecutionPrefix(projectId: string) {
|
|
|
|
|
|
return `${PROJECT_PREFIX}/${projectId}/executions`;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function getTaskPrefix(projectId: string, executionId: string) {
|
|
|
|
|
|
return `${getExecutionPrefix(projectId)}/${executionId}/tasks`;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 归一化项目数据 */
|
2026-06-11 14:02:26 +08:00
|
|
|
|
export function normalizeProject(project: ProjectResponse): Api.Project.Project {
|
2026-05-09 11:30:34 +08:00
|
|
|
|
return {
|
|
|
|
|
|
...project,
|
|
|
|
|
|
id: normalizeStringId(project.id),
|
|
|
|
|
|
managerUserId: normalizeNullableStringId(project.managerUserId) ?? '',
|
|
|
|
|
|
productId: normalizeNullableStringId(project.productId),
|
|
|
|
|
|
plannedStartDate: normalizeProjectLocalDate(project.plannedStartDate),
|
|
|
|
|
|
plannedEndDate: normalizeProjectLocalDate(project.plannedEndDate),
|
|
|
|
|
|
actualStartDate: normalizeProjectLocalDate(project.actualStartDate),
|
|
|
|
|
|
actualEndDate: normalizeProjectLocalDate(project.actualEndDate)
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 将项目详情组装为设置页数据 */
|
|
|
|
|
|
function createProjectSettings(project: Api.Project.Project): Api.Project.ProjectSettings {
|
|
|
|
|
|
return {
|
|
|
|
|
|
baseInfo: {
|
|
|
|
|
|
id: project.id,
|
|
|
|
|
|
projectCode: project.projectCode,
|
|
|
|
|
|
projectName: project.projectName,
|
|
|
|
|
|
directionCode: project.directionCode,
|
|
|
|
|
|
projectType: project.projectType,
|
|
|
|
|
|
productId: project.productId,
|
|
|
|
|
|
productName: project.productName ?? null,
|
|
|
|
|
|
managerUserId: project.managerUserId,
|
|
|
|
|
|
managerUserNickname: project.managerUserNickname ?? null,
|
|
|
|
|
|
statusCode: project.statusCode,
|
|
|
|
|
|
plannedStartDate: project.plannedStartDate,
|
|
|
|
|
|
plannedEndDate: project.plannedEndDate,
|
|
|
|
|
|
actualStartDate: project.actualStartDate,
|
|
|
|
|
|
actualEndDate: project.actualEndDate,
|
|
|
|
|
|
projectDesc: project.projectDesc,
|
|
|
|
|
|
lastStatusReason: project.lastStatusReason
|
|
|
|
|
|
},
|
|
|
|
|
|
lifecycle: {
|
|
|
|
|
|
statusCode: project.statusCode,
|
|
|
|
|
|
lastStatusReason: project.lastStatusReason,
|
|
|
|
|
|
availableActions: getProjectLifecycleActions(project.statusCode)
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 获取项目分页 */
|
|
|
|
|
|
export async function fetchGetProjectPage(params?: Api.Project.ProjectSearchParams) {
|
|
|
|
|
|
const result = await request<ProjectPageResponse>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_PREFIX}/page`,
|
|
|
|
|
|
method: 'get',
|
|
|
|
|
|
params
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<ProjectPageResponse>, data => ({
|
|
|
|
|
|
...data,
|
|
|
|
|
|
list: data.list.map(normalizeProject)
|
|
|
|
|
|
}));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-11 14:02:26 +08:00
|
|
|
|
type ProjectOverviewSummaryResponse = Omit<Api.Project.ProjectOverviewSummary, 'total' | 'items'> & {
|
|
|
|
|
|
/** 后端 overview-summary 升级(total/items)灰度期间可能缺省,适配层兜底 */
|
|
|
|
|
|
total?: number | null;
|
|
|
|
|
|
items?: Api.Project.OverviewStatusItem[] | null;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/** 归一化项目概览统计:total/items 兜底,保证业务层拿到完整结构 */
|
|
|
|
|
|
function normalizeProjectOverviewSummary(data: ProjectOverviewSummaryResponse): Api.Project.ProjectOverviewSummary {
|
|
|
|
|
|
return {
|
|
|
|
|
|
...data,
|
|
|
|
|
|
statusCounts: data.statusCounts ?? {},
|
|
|
|
|
|
total: data.total ?? 0,
|
|
|
|
|
|
items: data.items ?? []
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-09 11:30:34 +08:00
|
|
|
|
/** 获取项目入口页概览统计 */
|
2026-06-11 14:02:26 +08:00
|
|
|
|
export async function fetchGetProjectOverviewSummary() {
|
|
|
|
|
|
const result = await request<ProjectOverviewSummaryResponse>({
|
2026-05-09 11:30:34 +08:00
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_PREFIX}/overview-summary`,
|
|
|
|
|
|
method: 'get'
|
|
|
|
|
|
});
|
2026-06-11 14:02:26 +08:00
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(
|
|
|
|
|
|
result as ServiceRequestResult<ProjectOverviewSummaryResponse>,
|
|
|
|
|
|
normalizeProjectOverviewSummary
|
|
|
|
|
|
);
|
2026-05-09 11:30:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 获取项目详情 */
|
|
|
|
|
|
export async function fetchGetProject(id: string) {
|
|
|
|
|
|
const result = await request<ProjectResponse>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_PREFIX}/get`,
|
|
|
|
|
|
method: 'get',
|
|
|
|
|
|
params: { id }
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<ProjectResponse>, normalizeProject);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-09 18:15:10 +08:00
|
|
|
|
/** 根据产品ID获取产品下的所有项目 */
|
|
|
|
|
|
export async function fetchGetProjectListByProductId(productId: string) {
|
|
|
|
|
|
const result = await request<ProjectResponse[]>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_PREFIX}/list-by-product`,
|
|
|
|
|
|
method: 'get',
|
|
|
|
|
|
params: { productId }
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<ProjectResponse[]>, data => data.map(normalizeProject));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-09 11:30:34 +08:00
|
|
|
|
/** 创建项目 */
|
|
|
|
|
|
export async function fetchCreateProject(data: Api.Project.SaveProjectParams) {
|
|
|
|
|
|
const result = await request<string | number>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_PREFIX}/create`,
|
|
|
|
|
|
method: 'post',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<string | number>, normalizeStringId);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-12 21:41:39 +08:00
|
|
|
|
/** 创建项目(含初始团队,原子接口) */
|
|
|
|
|
|
export async function fetchCreateProjectWithTeam(data: Api.Project.CreateProjectWithTeamParams) {
|
|
|
|
|
|
const result = await request<string | number>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_PREFIX}/create-with-team`,
|
|
|
|
|
|
method: 'post',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<string | number>, normalizeStringId);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-09 11:30:34 +08:00
|
|
|
|
/** 更新项目 */
|
|
|
|
|
|
export function fetchUpdateProject(data: Api.Project.UpdateProjectParams) {
|
|
|
|
|
|
return request<boolean>({
|
|
|
|
|
|
url: `${PROJECT_PREFIX}/update`,
|
|
|
|
|
|
method: 'put',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 变更项目状态 */
|
|
|
|
|
|
export function fetchChangeProjectStatus(data: Api.Project.ChangeProjectStatusParams) {
|
|
|
|
|
|
return request<boolean>({
|
|
|
|
|
|
url: `${PROJECT_PREFIX}/change-status`,
|
|
|
|
|
|
method: 'post',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 删除项目 */
|
|
|
|
|
|
export function fetchDeleteProject(data: Api.Project.DeleteProjectParams) {
|
|
|
|
|
|
return request<boolean>({
|
|
|
|
|
|
url: `${PROJECT_PREFIX}/delete`,
|
|
|
|
|
|
method: 'post',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 获取项目上下文 */
|
|
|
|
|
|
export async function fetchGetProjectContext(id: string) {
|
|
|
|
|
|
const result = await request<ProjectContextResponse>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_PREFIX}/${id}/context`,
|
|
|
|
|
|
method: 'get'
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<ProjectContextResponse>, data => ({
|
|
|
|
|
|
...data,
|
|
|
|
|
|
currentProject: {
|
|
|
|
|
|
...data.currentProject,
|
|
|
|
|
|
id: normalizeStringId(data.currentProject.id)
|
|
|
|
|
|
},
|
|
|
|
|
|
navs: data.navs.map(nav => ({
|
|
|
|
|
|
...nav,
|
|
|
|
|
|
id: normalizeStringId(nav.id)
|
|
|
|
|
|
}))
|
|
|
|
|
|
}));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 获取项目成员列表 */
|
|
|
|
|
|
export async function fetchGetProjectMembers(id: string) {
|
|
|
|
|
|
const result = await request<ProjectMemberResponse[]>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_PREFIX}/${id}/members`,
|
|
|
|
|
|
method: 'get'
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<ProjectMemberResponse[]>, data =>
|
|
|
|
|
|
data.map(normalizeProjectMember)
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 创建项目成员 */
|
|
|
|
|
|
export async function fetchCreateProjectMember(id: string, data: Api.Project.CreateProjectMemberParams) {
|
|
|
|
|
|
const result = await request<string | number>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_PREFIX}/${id}/members`,
|
|
|
|
|
|
method: 'post',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<string | number>, normalizeStringId);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 更新项目成员 */
|
|
|
|
|
|
export function fetchUpdateProjectMember(id: string, memberId: string, data: Api.Project.UpdateProjectMemberParams) {
|
|
|
|
|
|
return request<boolean>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_PREFIX}/${id}/members/${memberId}`,
|
|
|
|
|
|
method: 'put',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 移出项目成员 */
|
|
|
|
|
|
export function fetchInactiveProjectMember(
|
|
|
|
|
|
id: string,
|
|
|
|
|
|
memberId: string,
|
|
|
|
|
|
data: Api.Project.InactiveProjectMemberParams
|
|
|
|
|
|
) {
|
|
|
|
|
|
return request<boolean>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_PREFIX}/${id}/members/${memberId}/inactive`,
|
|
|
|
|
|
method: 'post',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-18 22:25:04 +08:00
|
|
|
|
export async function fetchBatchCreateProjectMembers(id: string, data: Api.Project.BatchCreateProjectMembersParams) {
|
|
|
|
|
|
const result = await request<Array<string | number>>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_PREFIX}/${id}/members/batch`,
|
|
|
|
|
|
method: 'post',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<Array<string | number>>, list =>
|
|
|
|
|
|
Array.isArray(list) ? list.map(normalizeStringId) : []
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export function fetchBatchInactiveProjectMembers(id: string, data: Api.Project.BatchInactiveProjectMembersParams) {
|
|
|
|
|
|
return request<boolean>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_PREFIX}/${id}/members/batch/inactive`,
|
|
|
|
|
|
method: 'post',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-09 11:30:34 +08:00
|
|
|
|
/** 获取项目设置 */
|
|
|
|
|
|
export async function fetchGetProjectSettings(id: string) {
|
|
|
|
|
|
const result = await fetchGetProject(id);
|
|
|
|
|
|
|
|
|
|
|
|
if (result.error || !result.data) {
|
|
|
|
|
|
return result as ServiceRequestResult<Api.Project.ProjectSettings>;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
...result,
|
|
|
|
|
|
data: createProjectSettings(result.data)
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 更新项目设置基础信息 */
|
|
|
|
|
|
export async function fetchUpdateProjectSettingBaseInfo(
|
|
|
|
|
|
id: string,
|
|
|
|
|
|
data: Api.Project.UpdateProjectSettingBaseInfoParams
|
|
|
|
|
|
) {
|
|
|
|
|
|
const detailResult = await fetchGetProject(id);
|
|
|
|
|
|
|
|
|
|
|
|
if (detailResult.error || !detailResult.data) {
|
|
|
|
|
|
return detailResult as ServiceRequestResult<boolean>;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return fetchUpdateProject({
|
|
|
|
|
|
id,
|
|
|
|
|
|
projectCode: detailResult.data.projectCode,
|
|
|
|
|
|
projectName: data.projectName,
|
|
|
|
|
|
directionCode: data.directionCode,
|
|
|
|
|
|
projectType: data.projectType,
|
|
|
|
|
|
productId: detailResult.data.productId,
|
|
|
|
|
|
managerUserId: detailResult.data.managerUserId,
|
|
|
|
|
|
plannedStartDate: data.plannedStartDate,
|
|
|
|
|
|
plannedEndDate: data.plannedEndDate,
|
|
|
|
|
|
actualStartDate: detailResult.data.actualStartDate,
|
|
|
|
|
|
actualEndDate: detailResult.data.actualEndDate,
|
|
|
|
|
|
projectDesc: data.projectDesc
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 获取项目执行分页 */
|
|
|
|
|
|
export async function fetchGetProjectExecutionPage(
|
|
|
|
|
|
projectId: string,
|
|
|
|
|
|
params?: Api.Project.ProjectExecutionSearchParams
|
|
|
|
|
|
) {
|
|
|
|
|
|
const result = await request<ProjectExecutionPageResponse>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${getExecutionPrefix(projectId)}/page`,
|
|
|
|
|
|
method: 'get',
|
|
|
|
|
|
params
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<ProjectExecutionPageResponse>, data => ({
|
|
|
|
|
|
...data,
|
|
|
|
|
|
list: data.list.map(normalizeProjectExecution)
|
2026-06-04 11:26:51 +08:00
|
|
|
|
}));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 获取工作台「我负责的执行」(跨项目聚合,owner 隐式取当前登录用户) */
|
|
|
|
|
|
export async function fetchGetMyExecutionPage(params?: Api.Project.MyExecutionSearchParams) {
|
|
|
|
|
|
type MyExecutionPageResponse = Api.Project.PageResult<MyExecutionResponse>;
|
|
|
|
|
|
const result = await request<MyExecutionPageResponse>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_PREFIX}/me/executions/page`,
|
|
|
|
|
|
method: 'get',
|
|
|
|
|
|
params
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<MyExecutionPageResponse>, data => ({
|
|
|
|
|
|
...data,
|
|
|
|
|
|
list: data.list.map(normalizeMyExecution)
|
|
|
|
|
|
}));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 获取工作台「我参与的项目」(成员视角,附我的角色与任务量;隐式取当前登录用户) */
|
|
|
|
|
|
export async function fetchGetMyParticipatedProjectPage(params?: Api.Project.MyProjectSearchParams) {
|
|
|
|
|
|
type MyParticipatedProjectPageResponse = Api.Project.PageResult<MyParticipatedProjectResponse>;
|
|
|
|
|
|
const result = await request<MyParticipatedProjectPageResponse>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_PREFIX}/me/participated/page`,
|
|
|
|
|
|
method: 'get',
|
|
|
|
|
|
params
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<MyParticipatedProjectPageResponse>, data => ({
|
|
|
|
|
|
...data,
|
|
|
|
|
|
list: data.list.map(normalizeMyParticipatedProject)
|
|
|
|
|
|
}));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 获取工作台「我负责的项目」(项目负责人视角,附聚合统计与成员负载;隐式取当前登录用户) */
|
|
|
|
|
|
export async function fetchGetMyOwnedProjectPage(params?: Api.Project.MyProjectSearchParams) {
|
|
|
|
|
|
type MyOwnedProjectPageResponse = Api.Project.PageResult<MyOwnedProjectResponse>;
|
|
|
|
|
|
const result = await request<MyOwnedProjectPageResponse>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_PREFIX}/me/owned/page`,
|
|
|
|
|
|
method: 'get',
|
|
|
|
|
|
params
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<MyOwnedProjectPageResponse>, data => ({
|
|
|
|
|
|
...data,
|
|
|
|
|
|
list: data.list.map(normalizeMyOwnedProject)
|
2026-05-09 11:30:34 +08:00
|
|
|
|
}));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 获取项目执行状态看板 */
|
|
|
|
|
|
export function fetchGetProjectExecutionStatusBoard(
|
|
|
|
|
|
projectId: string,
|
|
|
|
|
|
params?: Api.Project.ProjectExecutionStatusBoardParams
|
|
|
|
|
|
) {
|
|
|
|
|
|
return request<StatusBoardResponse>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${getExecutionPrefix(projectId)}/status-board`,
|
|
|
|
|
|
method: 'get',
|
|
|
|
|
|
params
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 获取项目执行详情 */
|
|
|
|
|
|
export async function fetchGetProjectExecution(projectId: string, executionId: string) {
|
|
|
|
|
|
const result = await request<ProjectExecutionResponse>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${getExecutionPrefix(projectId)}/${executionId}`,
|
|
|
|
|
|
method: 'get'
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<ProjectExecutionResponse>, normalizeProjectExecution);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 创建项目执行 */
|
2026-05-12 21:41:39 +08:00
|
|
|
|
export async function fetchCreateProjectExecution(projectId: string, data: Api.Project.CreateProjectExecutionParams) {
|
2026-05-09 11:30:34 +08:00
|
|
|
|
const result = await request<string | number>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: getExecutionPrefix(projectId),
|
|
|
|
|
|
method: 'post',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<string | number>, normalizeStringId);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 更新项目执行 */
|
|
|
|
|
|
export function fetchUpdateProjectExecution(
|
|
|
|
|
|
projectId: string,
|
|
|
|
|
|
executionId: string,
|
2026-05-12 21:41:39 +08:00
|
|
|
|
data: Api.Project.UpdateProjectExecutionParams
|
2026-05-09 11:30:34 +08:00
|
|
|
|
) {
|
|
|
|
|
|
return request<boolean>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${getExecutionPrefix(projectId)}/${executionId}`,
|
|
|
|
|
|
method: 'put',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 变更项目执行负责人 */
|
|
|
|
|
|
export function fetchChangeProjectExecutionOwner(
|
|
|
|
|
|
projectId: string,
|
|
|
|
|
|
executionId: string,
|
|
|
|
|
|
data: Api.Project.ChangeExecutionOwnerParams
|
|
|
|
|
|
) {
|
|
|
|
|
|
return request<boolean>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${getExecutionPrefix(projectId)}/${executionId}/change-owner`,
|
|
|
|
|
|
method: 'post',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-12 21:41:39 +08:00
|
|
|
|
/** 删除项目执行 */
|
|
|
|
|
|
export function fetchDeleteProjectExecution(
|
|
|
|
|
|
projectId: string,
|
|
|
|
|
|
executionId: string,
|
|
|
|
|
|
data: Api.Project.DeleteProjectExecutionParams
|
|
|
|
|
|
) {
|
|
|
|
|
|
return request<boolean>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${getExecutionPrefix(projectId)}/${executionId}`,
|
|
|
|
|
|
method: 'delete',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-21 21:42:23 +08:00
|
|
|
|
/** 执行删除预检(spec §2.1:返回是否含下挂数据,用于前端弹层分流) */
|
|
|
|
|
|
export function fetchPrecheckDeleteProjectExecution(projectId: string, executionId: string) {
|
|
|
|
|
|
return request<Api.Project.ProjectExecutionDeletePrecheck>({
|
|
|
|
|
|
url: `${getExecutionPrefix(projectId)}/${executionId}/delete-precheck`,
|
|
|
|
|
|
method: 'get'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-09 11:30:34 +08:00
|
|
|
|
/** 变更项目执行状态 */
|
|
|
|
|
|
export function fetchChangeProjectExecutionStatus(
|
|
|
|
|
|
projectId: string,
|
|
|
|
|
|
executionId: string,
|
|
|
|
|
|
data: Api.Project.ChangeExecutionStatusParams
|
|
|
|
|
|
) {
|
|
|
|
|
|
return request<boolean>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${getExecutionPrefix(projectId)}/${executionId}/change-status`,
|
|
|
|
|
|
method: 'post',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-12 21:41:39 +08:00
|
|
|
|
/** 获取项目执行协办人 */
|
|
|
|
|
|
export async function fetchGetProjectExecutionAssignees(projectId: string, executionId: string) {
|
|
|
|
|
|
const result = await request<ExecutionAssigneeResponse[]>({
|
2026-05-09 11:30:34 +08:00
|
|
|
|
...safeJsonRequestConfig,
|
2026-05-12 21:41:39 +08:00
|
|
|
|
url: `${getExecutionPrefix(projectId)}/${executionId}/assignees`,
|
2026-05-09 11:30:34 +08:00
|
|
|
|
method: 'get'
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2026-05-12 21:41:39 +08:00
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<ExecutionAssigneeResponse[]>, data =>
|
|
|
|
|
|
data.map(normalizeExecutionAssignee)
|
2026-05-09 11:30:34 +08:00
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-12 21:41:39 +08:00
|
|
|
|
/** 创建项目执行协办人 */
|
|
|
|
|
|
export async function fetchCreateProjectExecutionAssignee(
|
2026-05-09 11:30:34 +08:00
|
|
|
|
projectId: string,
|
|
|
|
|
|
executionId: string,
|
2026-05-12 21:41:39 +08:00
|
|
|
|
data: Api.Project.CreateExecutionAssigneeParams
|
2026-05-09 11:30:34 +08:00
|
|
|
|
) {
|
|
|
|
|
|
const result = await request<string | number>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
2026-05-12 21:41:39 +08:00
|
|
|
|
url: `${getExecutionPrefix(projectId)}/${executionId}/assignees`,
|
2026-05-09 11:30:34 +08:00
|
|
|
|
method: 'post',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<string | number>, normalizeStringId);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-12 21:41:39 +08:00
|
|
|
|
/** 移除项目执行协办人 */
|
|
|
|
|
|
export function fetchInactiveProjectExecutionAssignee(
|
2026-05-09 11:30:34 +08:00
|
|
|
|
projectId: string,
|
|
|
|
|
|
executionId: string,
|
2026-05-12 21:41:39 +08:00
|
|
|
|
payload: { assigneeId: string; data: Api.Project.InactiveExecutionAssigneeParams }
|
2026-05-09 11:30:34 +08:00
|
|
|
|
) {
|
|
|
|
|
|
return request<boolean>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
2026-05-12 21:41:39 +08:00
|
|
|
|
url: `${getExecutionPrefix(projectId)}/${executionId}/assignees/${payload.assigneeId}/inactive`,
|
2026-05-09 11:30:34 +08:00
|
|
|
|
method: 'post',
|
|
|
|
|
|
data: payload.data
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-12 21:41:39 +08:00
|
|
|
|
/** 获取项目执行协办人变更历史分页 */
|
|
|
|
|
|
export async function fetchGetProjectExecutionAssigneeLogPage(
|
2026-05-09 11:30:34 +08:00
|
|
|
|
projectId: string,
|
|
|
|
|
|
executionId: string,
|
2026-05-12 21:41:39 +08:00
|
|
|
|
params?: Api.Project.ExecutionAssigneeLogSearchParams
|
2026-05-09 11:30:34 +08:00
|
|
|
|
) {
|
2026-05-12 21:41:39 +08:00
|
|
|
|
const result = await request<Api.Project.PageResult<ExecutionAssigneeLogResponse>>({
|
2026-05-09 11:30:34 +08:00
|
|
|
|
...safeJsonRequestConfig,
|
2026-05-12 21:41:39 +08:00
|
|
|
|
url: `${getExecutionPrefix(projectId)}/${executionId}/assignee-logs`,
|
2026-05-09 11:30:34 +08:00
|
|
|
|
method: 'get',
|
|
|
|
|
|
params
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2026-05-12 21:41:39 +08:00
|
|
|
|
return mapServiceResult(
|
|
|
|
|
|
result as ServiceRequestResult<Api.Project.PageResult<ExecutionAssigneeLogResponse>>,
|
|
|
|
|
|
data => ({
|
|
|
|
|
|
...data,
|
|
|
|
|
|
list: data.list.map(normalizeExecutionAssigneeLog)
|
|
|
|
|
|
})
|
|
|
|
|
|
);
|
2026-05-09 11:30:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 获取项目任务分页 */
|
|
|
|
|
|
export async function fetchGetProjectTaskPage(
|
|
|
|
|
|
projectId: string,
|
|
|
|
|
|
executionId: string,
|
|
|
|
|
|
params?: Api.Project.ProjectTaskSearchParams
|
|
|
|
|
|
) {
|
|
|
|
|
|
const result = await request<ProjectTaskPageResponse>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${getTaskPrefix(projectId, executionId)}/page`,
|
|
|
|
|
|
method: 'get',
|
|
|
|
|
|
params
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<ProjectTaskPageResponse>, data => ({
|
|
|
|
|
|
...data,
|
|
|
|
|
|
list: data.list.map(normalizeProjectTask)
|
|
|
|
|
|
}));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 获取项目任务状态看板 */
|
|
|
|
|
|
export function fetchGetProjectTaskStatusBoard(
|
|
|
|
|
|
projectId: string,
|
|
|
|
|
|
executionId: string,
|
|
|
|
|
|
params?: Api.Project.ProjectTaskStatusBoardParams
|
|
|
|
|
|
) {
|
|
|
|
|
|
return request<StatusBoardResponse>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${getTaskPrefix(projectId, executionId)}/status-board`,
|
|
|
|
|
|
method: 'get',
|
|
|
|
|
|
params
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-14 09:05:08 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 任务看板按状态分组的分页接口。
|
|
|
|
|
|
*
|
|
|
|
|
|
* 看板模式专用:一次请求拿到所有列(或指定列)的首屏 + 总数,替代"5 列 5 次 page"的旧方式。
|
|
|
|
|
|
* 列内向下滚续页时再传 `statusCode=[X]&pageNo=N+1` 单列查询。
|
|
|
|
|
|
*/
|
|
|
|
|
|
export async function fetchGetProjectTaskBoardPage(
|
|
|
|
|
|
projectId: string,
|
|
|
|
|
|
executionId: string,
|
|
|
|
|
|
params?: Api.Project.ProjectTaskBoardPageParams
|
|
|
|
|
|
) {
|
|
|
|
|
|
const result = await request<ProjectTaskBoardPageResponse>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${getTaskPrefix(projectId, executionId)}/board-page`,
|
|
|
|
|
|
method: 'get',
|
|
|
|
|
|
params
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<ProjectTaskBoardPageResponse>, data => ({
|
|
|
|
|
|
items: data.items.map(item => ({
|
|
|
|
|
|
...item,
|
|
|
|
|
|
list: item.list.map(normalizeProjectTask)
|
|
|
|
|
|
}))
|
|
|
|
|
|
}));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-09 11:30:34 +08:00
|
|
|
|
/** 获取项目任务详情 */
|
|
|
|
|
|
export async function fetchGetProjectTask(projectId: string, executionId: string, taskId: string) {
|
|
|
|
|
|
const result = await request<ProjectTaskResponse>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${getTaskPrefix(projectId, executionId)}/${taskId}`,
|
|
|
|
|
|
method: 'get'
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<ProjectTaskResponse>, normalizeProjectTask);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 创建项目任务 */
|
|
|
|
|
|
export async function fetchCreateProjectTask(
|
|
|
|
|
|
projectId: string,
|
|
|
|
|
|
executionId: string,
|
|
|
|
|
|
data: Api.Project.SaveProjectTaskParams
|
|
|
|
|
|
) {
|
|
|
|
|
|
const result = await request<string | number>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: getTaskPrefix(projectId, executionId),
|
|
|
|
|
|
method: 'post',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<string | number>, normalizeStringId);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 更新项目任务 */
|
|
|
|
|
|
export function fetchUpdateProjectTask(
|
|
|
|
|
|
projectId: string,
|
|
|
|
|
|
executionId: string,
|
|
|
|
|
|
payload: { taskId: string; data: Api.Project.SaveProjectTaskParams }
|
|
|
|
|
|
) {
|
|
|
|
|
|
return request<boolean>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${getTaskPrefix(projectId, executionId)}/${payload.taskId}`,
|
|
|
|
|
|
method: 'put',
|
|
|
|
|
|
data: payload.data
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-12 21:41:39 +08:00
|
|
|
|
/** 删除项目任务 */
|
|
|
|
|
|
// eslint-disable-next-line max-params
|
|
|
|
|
|
export function fetchDeleteProjectTask(
|
|
|
|
|
|
projectId: string,
|
|
|
|
|
|
executionId: string,
|
|
|
|
|
|
taskId: string,
|
|
|
|
|
|
data: Api.Project.DeleteProjectTaskParams
|
|
|
|
|
|
) {
|
|
|
|
|
|
return request<boolean>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${getTaskPrefix(projectId, executionId)}/${taskId}`,
|
|
|
|
|
|
method: 'delete',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-21 21:42:23 +08:00
|
|
|
|
/** 任务删除预检(spec §2.1) */
|
|
|
|
|
|
export function fetchPrecheckDeleteProjectTask(projectId: string, executionId: string, taskId: string) {
|
|
|
|
|
|
return request<Api.Project.ProjectTaskDeletePrecheck>({
|
|
|
|
|
|
url: `${getTaskPrefix(projectId, executionId)}/${taskId}/delete-precheck`,
|
|
|
|
|
|
method: 'get'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-09 11:30:34 +08:00
|
|
|
|
/** 变更项目任务状态 */
|
|
|
|
|
|
export function fetchChangeProjectTaskStatus(
|
|
|
|
|
|
projectId: string,
|
|
|
|
|
|
executionId: string,
|
|
|
|
|
|
payload: { taskId: string; data: Api.Project.ChangeTaskStatusParams }
|
|
|
|
|
|
) {
|
|
|
|
|
|
return request<boolean>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${getTaskPrefix(projectId, executionId)}/${payload.taskId}/change-status`,
|
|
|
|
|
|
method: 'post',
|
|
|
|
|
|
data: payload.data
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2026-05-13 21:13:21 +08:00
|
|
|
|
|
2026-05-23 14:22:58 +08:00
|
|
|
|
// ============= 项目级跨执行任务(不带 executionId 路径段) =============
|
|
|
|
|
|
// 调试文档:所有接口挂在 /project/project/{projectId}/tasks/* 下;通过 involveUserId / ownerId / executionIds 等
|
|
|
|
|
|
// 入参组合表达"我的任务 / 项目全部 / 指定执行"等视角。原有执行级 {eid}/tasks/page 等保留不动。
|
|
|
|
|
|
|
|
|
|
|
|
function getProjectTasksPrefix(projectId: string) {
|
|
|
|
|
|
return `${PROJECT_PREFIX}/${projectId}/tasks`;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 项目级跨执行任务分页 */
|
|
|
|
|
|
export async function fetchGetProjectTaskPageCross(
|
|
|
|
|
|
projectId: string,
|
|
|
|
|
|
params?: Api.Project.ProjectTaskCrossSearchParams
|
|
|
|
|
|
) {
|
|
|
|
|
|
const result = await request<ProjectTaskPageResponse>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${getProjectTasksPrefix(projectId)}/page`,
|
|
|
|
|
|
method: 'get',
|
|
|
|
|
|
params
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<ProjectTaskPageResponse>, data => ({
|
|
|
|
|
|
...data,
|
|
|
|
|
|
list: data.list.map(normalizeProjectTask)
|
|
|
|
|
|
}));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 项目级跨执行任务状态看板 */
|
|
|
|
|
|
export function fetchGetProjectTaskStatusBoardCross(
|
|
|
|
|
|
projectId: string,
|
|
|
|
|
|
params?: Api.Project.ProjectTaskCrossStatusBoardParams
|
|
|
|
|
|
) {
|
|
|
|
|
|
return request<StatusBoardResponse>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${getProjectTasksPrefix(projectId)}/status-board`,
|
|
|
|
|
|
method: 'get',
|
|
|
|
|
|
params
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 项目级跨执行任务看板分页(每列共用同一组 pageNo / pageSize;列内固定 plannedEndDate ASC, id DESC) */
|
|
|
|
|
|
export async function fetchGetProjectTaskBoardPageCross(
|
|
|
|
|
|
projectId: string,
|
|
|
|
|
|
params?: Api.Project.ProjectTaskCrossBoardPageParams
|
|
|
|
|
|
) {
|
|
|
|
|
|
const result = await request<ProjectTaskBoardPageResponse>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${getProjectTasksPrefix(projectId)}/board-page`,
|
|
|
|
|
|
method: 'get',
|
|
|
|
|
|
params
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<ProjectTaskBoardPageResponse>, data => ({
|
|
|
|
|
|
items: data.items.map(item => ({
|
|
|
|
|
|
...item,
|
|
|
|
|
|
list: item.list.map(normalizeProjectTask)
|
|
|
|
|
|
}))
|
|
|
|
|
|
}));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 项目级"今日小条"汇总(4 个数字 + 服务器日期边界)。
|
|
|
|
|
|
*
|
2026-05-29 16:40:25 +08:00
|
|
|
|
* scope=all 必须有 project:task:query 权限,否则 403(PROJECT_OBJECT_PERMISSION_DENIED)。
|
2026-05-23 14:22:58 +08:00
|
|
|
|
* 前端切到"项目全部"视角前应已基于权限码隐藏入口;如真被 403,UI 应自动切回"我的"。
|
|
|
|
|
|
*/
|
|
|
|
|
|
export function fetchGetProjectTaskSummary(projectId: string, params?: Api.Project.ProjectTaskSummaryParams) {
|
|
|
|
|
|
return request<Api.Project.ProjectTaskSummary>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${getProjectTasksPrefix(projectId)}/summary`,
|
|
|
|
|
|
method: 'get',
|
|
|
|
|
|
params
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-12 21:41:39 +08:00
|
|
|
|
type TaskWorklogPageResponse = Api.Project.PageResult<TaskWorklogResponse>;
|
|
|
|
|
|
|
|
|
|
|
|
function getWorklogPrefix(projectId: string, executionId: string, taskId: string) {
|
|
|
|
|
|
return `${getTaskPrefix(projectId, executionId)}/${taskId}/worklogs`;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 获取任务工时分页 */
|
|
|
|
|
|
// eslint-disable-next-line max-params
|
|
|
|
|
|
export async function fetchGetProjectTaskWorklogPage(
|
|
|
|
|
|
projectId: string,
|
|
|
|
|
|
executionId: string,
|
|
|
|
|
|
taskId: string,
|
|
|
|
|
|
params?: Api.Project.TaskWorklogSearchParams
|
|
|
|
|
|
) {
|
|
|
|
|
|
const result = await request<TaskWorklogPageResponse>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: getWorklogPrefix(projectId, executionId, taskId),
|
|
|
|
|
|
method: 'get',
|
|
|
|
|
|
params
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<TaskWorklogPageResponse>, data => ({
|
|
|
|
|
|
...data,
|
|
|
|
|
|
list: data.list.map(normalizeTaskWorklog)
|
|
|
|
|
|
}));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 新增任务工时 */
|
|
|
|
|
|
// eslint-disable-next-line max-params
|
|
|
|
|
|
export async function fetchCreateProjectTaskWorklog(
|
|
|
|
|
|
projectId: string,
|
|
|
|
|
|
executionId: string,
|
|
|
|
|
|
taskId: string,
|
|
|
|
|
|
data: Api.Project.SaveTaskWorklogParams
|
|
|
|
|
|
) {
|
|
|
|
|
|
const result = await request<string | number>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: getWorklogPrefix(projectId, executionId, taskId),
|
|
|
|
|
|
method: 'post',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<string | number>, normalizeStringId);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 修改任务工时 */
|
|
|
|
|
|
// eslint-disable-next-line max-params
|
|
|
|
|
|
export function fetchUpdateProjectTaskWorklog(
|
|
|
|
|
|
projectId: string,
|
|
|
|
|
|
executionId: string,
|
|
|
|
|
|
taskId: string,
|
|
|
|
|
|
payload: { worklogId: string; data: Api.Project.SaveTaskWorklogParams }
|
|
|
|
|
|
) {
|
|
|
|
|
|
return request<boolean>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${getWorklogPrefix(projectId, executionId, taskId)}/${payload.worklogId}`,
|
|
|
|
|
|
method: 'put',
|
|
|
|
|
|
data: payload.data
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 删除任务工时 */
|
|
|
|
|
|
// eslint-disable-next-line max-params
|
|
|
|
|
|
export function fetchDeleteProjectTaskWorklog(
|
|
|
|
|
|
projectId: string,
|
|
|
|
|
|
executionId: string,
|
|
|
|
|
|
taskId: string,
|
|
|
|
|
|
worklogId: string
|
|
|
|
|
|
) {
|
|
|
|
|
|
return request<boolean>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${getWorklogPrefix(projectId, executionId, taskId)}/${worklogId}`,
|
|
|
|
|
|
method: 'delete'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 5.6 获取任务协办人列表(仅当前活跃) */
|
|
|
|
|
|
export async function fetchGetProjectTaskAssignees(projectId: string, executionId: string, taskId: string) {
|
|
|
|
|
|
const result = await request<TaskAssigneeFromApiResponse[]>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${getTaskPrefix(projectId, executionId)}/${taskId}/assignees`,
|
|
|
|
|
|
method: 'get'
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<TaskAssigneeFromApiResponse[]>, data =>
|
|
|
|
|
|
data.map(normalizeTaskAssignee)
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 5.7 加入任务协办人 */
|
|
|
|
|
|
// eslint-disable-next-line max-params
|
|
|
|
|
|
export async function fetchCreateProjectTaskAssignee(
|
|
|
|
|
|
projectId: string,
|
|
|
|
|
|
executionId: string,
|
|
|
|
|
|
taskId: string,
|
|
|
|
|
|
data: Api.Project.CreateTaskAssigneeParams
|
|
|
|
|
|
) {
|
|
|
|
|
|
const result = await request<string | number>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${getTaskPrefix(projectId, executionId)}/${taskId}/assignees`,
|
|
|
|
|
|
method: 'post',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<string | number>, normalizeStringId);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 5.8 退出任务协办人 */
|
|
|
|
|
|
// eslint-disable-next-line max-params
|
|
|
|
|
|
export function fetchInactiveProjectTaskAssignee(
|
|
|
|
|
|
projectId: string,
|
|
|
|
|
|
executionId: string,
|
|
|
|
|
|
taskId: string,
|
|
|
|
|
|
assigneeId: string,
|
|
|
|
|
|
data: Api.Project.InactiveTaskAssigneeParams
|
|
|
|
|
|
) {
|
|
|
|
|
|
return request<boolean>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${getTaskPrefix(projectId, executionId)}/${taskId}/assignees/${assigneeId}/inactive`,
|
|
|
|
|
|
method: 'post',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 5.9 任务协办人变更历史分页 */
|
|
|
|
|
|
// eslint-disable-next-line max-params
|
|
|
|
|
|
export async function fetchGetProjectTaskAssigneeLogPage(
|
|
|
|
|
|
projectId: string,
|
|
|
|
|
|
executionId: string,
|
|
|
|
|
|
taskId: string,
|
|
|
|
|
|
params?: Api.Project.TaskAssigneeLogSearchParams
|
|
|
|
|
|
) {
|
|
|
|
|
|
const result = await request<Api.Project.PageResult<TaskAssigneeLogResponse>>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${getTaskPrefix(projectId, executionId)}/${taskId}/assignee-logs`,
|
|
|
|
|
|
method: 'get',
|
|
|
|
|
|
params
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<Api.Project.PageResult<TaskAssigneeLogResponse>>, data => ({
|
|
|
|
|
|
...data,
|
|
|
|
|
|
list: data.list.map(normalizeTaskAssigneeLog)
|
|
|
|
|
|
}));
|
|
|
|
|
|
}
|
2026-05-13 21:20:59 +08:00
|
|
|
|
|
2026-05-13 21:13:21 +08:00
|
|
|
|
// ========== 项目需求 API ==========
|
|
|
|
|
|
const PROJECT_REQUIREMENT_PREFIX = `${WEB_SERVICE_PREFIX}/project/project/requirement`;
|
|
|
|
|
|
|
|
|
|
|
|
type ProjectRequirementResponse = Omit<
|
|
|
|
|
|
Api.Project.ProjectRequirement,
|
2026-05-13 23:09:35 +08:00
|
|
|
|
'id' | 'projectId' | 'parentId' | 'moduleId' | 'proposerId' | 'currentHandlerUserId' | 'sourceBizId' | 'attachments'
|
2026-05-13 21:13:21 +08:00
|
|
|
|
> & {
|
|
|
|
|
|
id: string | number;
|
|
|
|
|
|
projectId: string | number;
|
|
|
|
|
|
parentId: string | number;
|
|
|
|
|
|
moduleId: string | number;
|
|
|
|
|
|
proposerId: string | number;
|
|
|
|
|
|
currentHandlerUserId?: string | number | null;
|
|
|
|
|
|
sourceBizId?: string | number | null;
|
2026-05-13 23:09:35 +08:00
|
|
|
|
attachments?: AttachmentItemResponse[] | null;
|
2026-05-13 21:13:21 +08:00
|
|
|
|
children?: ProjectRequirementResponse[];
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
type ProjectRequirementPageResponse = Api.Project.PageResult<ProjectRequirementResponse>;
|
2026-05-22 14:05:25 +08:00
|
|
|
|
type ProjectRequirementReviewResponse = Omit<
|
|
|
|
|
|
Api.Project.ProjectRequirementReview,
|
|
|
|
|
|
'id' | 'requirementId' | 'operatorId' | 'attendees' | 'attachments'
|
|
|
|
|
|
> & {
|
|
|
|
|
|
id: string | number;
|
|
|
|
|
|
requirementId: string | number;
|
|
|
|
|
|
operatorId: string | number;
|
|
|
|
|
|
attendees?: Array<{
|
|
|
|
|
|
userId: string | number;
|
|
|
|
|
|
nickname: string;
|
|
|
|
|
|
}>;
|
|
|
|
|
|
attachments?: AttachmentItemResponse[] | null;
|
|
|
|
|
|
};
|
2026-05-13 21:13:21 +08:00
|
|
|
|
|
|
|
|
|
|
type ProjectRequirementModuleResponse = Omit<Api.Project.ProjectRequirementModule, 'id' | 'parentId' | 'projectId'> & {
|
|
|
|
|
|
id: string | number;
|
|
|
|
|
|
parentId: string | number;
|
|
|
|
|
|
projectId: string | number;
|
|
|
|
|
|
children?: ProjectRequirementModuleResponse[];
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-05-13 23:09:35 +08:00
|
|
|
|
type AttachmentItemResponse = Omit<Api.Project.AttachmentItem, 'fileId'> & {
|
|
|
|
|
|
fileId?: string | number;
|
|
|
|
|
|
id?: string | number;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
function normalizeAttachments(list?: AttachmentItemResponse[] | null): Api.Project.AttachmentItem[] | null {
|
|
|
|
|
|
if (!list) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return list.map(item => {
|
|
|
|
|
|
const rawId = item.fileId ?? item.id;
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
...item,
|
|
|
|
|
|
fileId: rawId === null || rawId === undefined ? '' : String(rawId)
|
|
|
|
|
|
};
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-13 21:13:21 +08:00
|
|
|
|
function normalizeProjectRequirement(requirement: ProjectRequirementResponse): Api.Project.ProjectRequirement {
|
|
|
|
|
|
return {
|
|
|
|
|
|
...requirement,
|
|
|
|
|
|
id: normalizeStringId(requirement.id),
|
|
|
|
|
|
projectId: normalizeStringId(requirement.projectId),
|
|
|
|
|
|
parentId: normalizeStringId(requirement.parentId),
|
|
|
|
|
|
moduleId: normalizeStringId(requirement.moduleId),
|
|
|
|
|
|
proposerId: normalizeStringId(requirement.proposerId),
|
|
|
|
|
|
currentHandlerUserId: normalizeNullableStringId(requirement.currentHandlerUserId),
|
|
|
|
|
|
sourceBizId: normalizeNullableStringId(requirement.sourceBizId),
|
2026-05-13 23:09:35 +08:00
|
|
|
|
attachments: normalizeAttachments(requirement.attachments),
|
2026-05-21 21:42:23 +08:00
|
|
|
|
progressRate: typeof requirement.progressRate === 'number' ? requirement.progressRate : 0,
|
2026-05-13 21:13:21 +08:00
|
|
|
|
children: requirement.children?.map(normalizeProjectRequirement)
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-22 14:05:25 +08:00
|
|
|
|
function normalizeProjectRequirementReview(
|
|
|
|
|
|
review: ProjectRequirementReviewResponse
|
|
|
|
|
|
): Api.Project.ProjectRequirementReview {
|
|
|
|
|
|
return {
|
|
|
|
|
|
...review,
|
|
|
|
|
|
id: normalizeStringId(review.id),
|
|
|
|
|
|
requirementId: normalizeStringId(review.requirementId),
|
|
|
|
|
|
operatorId: normalizeStringId(review.operatorId),
|
|
|
|
|
|
attendees: review.attendees?.map(item => ({
|
|
|
|
|
|
...item,
|
|
|
|
|
|
userId: normalizeStringId(item.userId)
|
|
|
|
|
|
})),
|
|
|
|
|
|
attachments: normalizeAttachments(review.attachments)
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-13 21:13:21 +08:00
|
|
|
|
function normalizeProjectRequirementModule(
|
|
|
|
|
|
module: ProjectRequirementModuleResponse
|
|
|
|
|
|
): Api.Project.ProjectRequirementModule {
|
|
|
|
|
|
return {
|
|
|
|
|
|
...module,
|
|
|
|
|
|
id: normalizeStringId(module.id),
|
|
|
|
|
|
parentId: normalizeStringId(module.parentId),
|
|
|
|
|
|
projectId: normalizeStringId(module.projectId),
|
|
|
|
|
|
children: module.children?.map(normalizeProjectRequirementModule)
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 获取项目需求分页列表 */
|
|
|
|
|
|
export async function fetchGetProjectRequirementPage(params?: Api.Project.ProjectRequirementSearchParams) {
|
|
|
|
|
|
const result = await request<ProjectRequirementPageResponse>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_REQUIREMENT_PREFIX}/page`,
|
|
|
|
|
|
method: 'get',
|
|
|
|
|
|
params
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<ProjectRequirementPageResponse>, data => ({
|
|
|
|
|
|
...data,
|
|
|
|
|
|
list: data.list.map(normalizeProjectRequirement)
|
|
|
|
|
|
}));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 获取项目需求树形列表 */
|
|
|
|
|
|
export async function fetchGetProjectRequirementTree(params?: Api.Project.ProjectRequirementSearchParams) {
|
|
|
|
|
|
const result = await request<ProjectRequirementPageResponse>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_REQUIREMENT_PREFIX}/tree`,
|
|
|
|
|
|
method: 'get',
|
|
|
|
|
|
params
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<ProjectRequirementPageResponse>, data => ({
|
|
|
|
|
|
...data,
|
|
|
|
|
|
list: data.list.map(normalizeProjectRequirement)
|
|
|
|
|
|
}));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 获取项目需求详情 */
|
|
|
|
|
|
export async function fetchGetProjectRequirement(id: string, projectId: string) {
|
|
|
|
|
|
const result = await request<ProjectRequirementResponse>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_REQUIREMENT_PREFIX}/get`,
|
|
|
|
|
|
method: 'get',
|
|
|
|
|
|
params: { id, projectId }
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<ProjectRequirementResponse>, normalizeProjectRequirement);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 创建项目需求 */
|
|
|
|
|
|
export async function fetchCreateProjectRequirement(data: Api.Project.SaveProjectRequirementParams) {
|
|
|
|
|
|
const result = await request<string | number>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_REQUIREMENT_PREFIX}/create`,
|
|
|
|
|
|
method: 'post',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<string | number>, normalizeStringId);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 更新项目需求 */
|
|
|
|
|
|
export function fetchUpdateProjectRequirement(data: Api.Project.UpdateProjectRequirementParams) {
|
|
|
|
|
|
return request<boolean>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_REQUIREMENT_PREFIX}/update`,
|
|
|
|
|
|
method: 'put',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 变更项目需求状态 */
|
|
|
|
|
|
export function fetchChangeProjectRequirementStatus(data: Api.Project.ChangeProjectRequirementStatusParams) {
|
|
|
|
|
|
return request<boolean>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_REQUIREMENT_PREFIX}/change-status`,
|
|
|
|
|
|
method: 'post',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 删除项目需求 */
|
|
|
|
|
|
export function fetchDeleteProjectRequirement(data: Api.Project.DeleteProjectRequirementParams) {
|
|
|
|
|
|
return request<boolean>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_REQUIREMENT_PREFIX}/delete`,
|
|
|
|
|
|
method: 'post',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 拆分项目需求 */
|
|
|
|
|
|
export async function fetchSplitProjectRequirement(data: Api.Project.SplitProjectRequirementParams) {
|
|
|
|
|
|
const result = await request<string | number>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_REQUIREMENT_PREFIX}/split`,
|
|
|
|
|
|
method: 'post',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<string | number>, normalizeStringId);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 关闭项目需求 */
|
|
|
|
|
|
export function fetchCloseProjectRequirement(data: Api.Project.CloseProjectRequirementParams) {
|
|
|
|
|
|
return request<boolean>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_REQUIREMENT_PREFIX}/close`,
|
|
|
|
|
|
method: 'post',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 获取项目需求可执行状态动作列表 */
|
|
|
|
|
|
export async function fetchGetProjectRequirementAllowedTransitions(requirementId: string, projectId: string) {
|
|
|
|
|
|
const result = await request<Api.Project.ProjectRequirementLifecycleAction[]>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_REQUIREMENT_PREFIX}/allowed-transitions`,
|
|
|
|
|
|
method: 'get',
|
|
|
|
|
|
params: { requirementId, projectId }
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(
|
|
|
|
|
|
result as ServiceRequestResult<Api.Project.ProjectRequirementLifecycleAction[]>,
|
|
|
|
|
|
data => data
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-18 16:49:12 +08:00
|
|
|
|
/** 批量获取项目需求可执行状态动作列表 */
|
|
|
|
|
|
export async function fetchGetProjectRequirementAllowedTransitionsBatch(
|
|
|
|
|
|
data: Api.Project.ProjectRequirementBatchReqVO
|
|
|
|
|
|
) {
|
|
|
|
|
|
const result = await request<Api.Project.ProjectRequirementAllowedTransitionBatchRespVO[]>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_REQUIREMENT_PREFIX}/allowed-transitions/batch`,
|
|
|
|
|
|
method: 'post',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(
|
|
|
|
|
|
result as ServiceRequestResult<Api.Project.ProjectRequirementAllowedTransitionBatchRespVO[]>,
|
|
|
|
|
|
data1 =>
|
|
|
|
|
|
data1.map(item => ({
|
|
|
|
|
|
requirementId: normalizeStringId(item.requirementId),
|
|
|
|
|
|
transitions: item.transitions
|
|
|
|
|
|
}))
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-22 14:05:25 +08:00
|
|
|
|
/** 提交项目需求评审 */
|
|
|
|
|
|
export async function fetchSubmitProjectRequirementReview(data: Api.Project.ProjectRequirementReviewSubmitParams) {
|
|
|
|
|
|
const result = await request<string | number>({
|
2026-05-13 21:13:21 +08:00
|
|
|
|
...safeJsonRequestConfig,
|
2026-05-22 14:05:25 +08:00
|
|
|
|
url: `${PROJECT_REQUIREMENT_PREFIX}/review/submit`,
|
|
|
|
|
|
method: 'post',
|
|
|
|
|
|
data
|
2026-05-13 21:13:21 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
2026-05-22 14:05:25 +08:00
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<string | number>, normalizeStringId);
|
2026-05-13 21:13:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-22 14:05:25 +08:00
|
|
|
|
/** 获取项目需求评审记录 */
|
|
|
|
|
|
export async function fetchGetProjectRequirementReview(projectId: string, requirementId: string) {
|
|
|
|
|
|
const result = await request<ProjectRequirementReviewResponse>({
|
2026-05-13 21:13:21 +08:00
|
|
|
|
...safeJsonRequestConfig,
|
2026-05-22 14:05:25 +08:00
|
|
|
|
url: `${PROJECT_REQUIREMENT_PREFIX}/review/get`,
|
|
|
|
|
|
method: 'get',
|
|
|
|
|
|
params: { projectId, requirementId }
|
2026-05-13 21:13:21 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
2026-05-22 14:05:25 +08:00
|
|
|
|
return mapServiceResult(
|
|
|
|
|
|
result as ServiceRequestResult<ProjectRequirementReviewResponse>,
|
|
|
|
|
|
normalizeProjectRequirementReview
|
|
|
|
|
|
);
|
2026-05-13 21:13:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-22 14:05:25 +08:00
|
|
|
|
/** 获取项目需求状态字典 */
|
|
|
|
|
|
export async function fetchGetProjectRequirementStatusDict() {
|
2026-05-13 21:13:21 +08:00
|
|
|
|
const result = await request<Api.Project.ProjectRequirementStatusDict[]>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
2026-05-22 14:05:25 +08:00
|
|
|
|
url: `${PROJECT_REQUIREMENT_PREFIX}/status/dict`,
|
2026-05-13 21:13:21 +08:00
|
|
|
|
method: 'get'
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<Api.Project.ProjectRequirementStatusDict[]>, data => data);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 获取项目需求模块树 */
|
|
|
|
|
|
export async function fetchGetProjectRequirementModuleTree(projectId: string) {
|
|
|
|
|
|
const result = await request<ProjectRequirementModuleResponse[]>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_REQUIREMENT_PREFIX}/module/tree`,
|
|
|
|
|
|
method: 'get',
|
|
|
|
|
|
params: { projectId }
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<ProjectRequirementModuleResponse[]>, data =>
|
|
|
|
|
|
data.map(normalizeProjectRequirementModule)
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 创建项目需求模块 */
|
|
|
|
|
|
export async function fetchCreateProjectRequirementModule(data: Api.Project.SaveProjectRequirementModuleParams) {
|
|
|
|
|
|
const result = await request<string | number>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_REQUIREMENT_PREFIX}/module/create`,
|
|
|
|
|
|
method: 'post',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mapServiceResult(result as ServiceRequestResult<string | number>, normalizeStringId);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 更新项目需求模块 */
|
|
|
|
|
|
export function fetchUpdateProjectRequirementModule(data: Api.Project.SaveProjectRequirementModuleParams) {
|
|
|
|
|
|
return request<boolean>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_REQUIREMENT_PREFIX}/module/update`,
|
|
|
|
|
|
method: 'put',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 删除项目需求模块 */
|
|
|
|
|
|
export function fetchDeleteProjectRequirementModule(data: Api.Project.DeleteProjectRequirementModuleParams) {
|
|
|
|
|
|
return request<boolean>({
|
|
|
|
|
|
...safeJsonRequestConfig,
|
|
|
|
|
|
url: `${PROJECT_REQUIREMENT_PREFIX}/module/delete`,
|
|
|
|
|
|
method: 'post',
|
|
|
|
|
|
data
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|