Files
cn-rdms-web/src/service/api/product.ts

501 lines
15 KiB
TypeScript
Raw Normal View History

import { WEB_SERVICE_PREFIX } from '@/constants/service';
import { request } from '../request';
import {
type ServiceRequestResult,
mapServiceResult,
normalizeNullableStringId,
normalizeStringId,
safeJsonRequestConfig
} from './shared';
import { normalizeProductMember, normalizeProductSettings } from './product-shared';
const PRODUCT_PREFIX = `${WEB_SERVICE_PREFIX}/project/product`;
type ProductResponse = Omit<Api.Product.Product, 'id' | 'managerUserId'> & {
id: string | number;
managerUserId?: string | number | null;
};
type ProductPageResponse = Api.Product.PageResult<ProductResponse>;
type ProductActivityTimelineItemResponse = Omit<
Api.Product.ProductActivityTimelineItem,
'id' | 'operatorUserId' | 'targetUserId' | 'occurredAt'
> & {
id: string | number;
operatorUserId?: string | number | null;
targetUserId?: string | number | null;
occurredAt: number | string;
};
type ProductActivityTimelinePageResponse = Omit<
Api.Product.PageResult<ProductActivityTimelineItemResponse>,
'total'
> & {
total: number | string;
};
function normalizeProduct(product: ProductResponse): Api.Product.Product {
return {
...product,
id: normalizeStringId(product.id),
managerUserId: normalizeNullableStringId(product.managerUserId) ?? ''
};
}
function normalizeOccurredAt(occurredAt: number | string) {
const value = Number(occurredAt);
return Number.isFinite(value) ? value : 0;
}
function normalizePageTotal(total: number | string) {
const value = Number(total);
return Number.isFinite(value) ? Math.max(0, value) : 0;
}
function normalizeProductActivityTimelineItem(
item: ProductActivityTimelineItemResponse
): Api.Product.ProductActivityTimelineItem {
return {
...item,
id: normalizeStringId(item.id),
operatorUserId: normalizeNullableStringId(item.operatorUserId),
targetUserId: normalizeNullableStringId(item.targetUserId),
occurredAt: normalizeOccurredAt(item.occurredAt)
};
}
function createProductActivityTimelinePageQuery(params: Api.Product.ProductActivityTimelinePageParams) {
const query = new URLSearchParams();
query.append('pageNo', String(params.pageNo));
query.append('pageSize', String(params.pageSize));
if (params.activityType) {
query.append('activityType', params.activityType);
}
params.actionTypes?.forEach(actionType => {
if (actionType) {
query.append('actionTypes', actionType);
}
});
if (params.startTime && params.endTime) {
query.append('startTime', params.startTime);
query.append('endTime', params.endTime);
}
return query.toString();
}
/** 鑾峰彇浜у搧鍒嗛〉 */
export async function fetchGetProductPage(params?: Api.Product.ProductSearchParams) {
const result = await request<ProductPageResponse>({
...safeJsonRequestConfig,
url: `${PRODUCT_PREFIX}/page`,
method: 'get',
params
});
return mapServiceResult(result as ServiceRequestResult<ProductPageResponse>, data => ({
...data,
list: data.list.map(normalizeProduct)
}));
}
/** 获取产品入口页概览统计 */
export function fetchGetProductOverviewSummary() {
return request<Api.Product.ProductOverviewSummary>({
...safeJsonRequestConfig,
url: `${PRODUCT_PREFIX}/overview-summary`,
method: 'get'
});
}
/** 鑾峰彇浜у搧璇︽儏 */
export async function fetchGetProduct(id: string) {
const result = await request<ProductResponse>({
...safeJsonRequestConfig,
url: `${PRODUCT_PREFIX}/get`,
method: 'get',
params: { id }
});
return mapServiceResult(result as ServiceRequestResult<ProductResponse>, normalizeProduct);
}
/** 鍒涘缓浜у搧 */
export async function fetchCreateProduct(data: Api.Product.SaveProductParams) {
const result = await request<string | number>({
...safeJsonRequestConfig,
url: `${PRODUCT_PREFIX}/create`,
method: 'post',
data
});
return mapServiceResult(result as ServiceRequestResult<string | number>, normalizeStringId);
}
/** 鏇存柊浜у搧 */
export function fetchUpdateProduct(data: Api.Product.UpdateProductParams) {
return request<boolean>({
url: `${PRODUCT_PREFIX}/update`,
method: 'put',
data
});
}
/** 鍙樻洿浜у搧鐘舵€? */
export function fetchChangeProductStatus(data: Api.Product.ChangeProductStatusParams) {
return request<boolean>({
url: `${PRODUCT_PREFIX}/change-status`,
method: 'post',
data
});
}
/** 鍒犻櫎浜у搧 */
export function fetchDeleteProduct(data: Api.Product.DeleteProductParams) {
return request<boolean>({
url: `${PRODUCT_PREFIX}/delete`,
method: 'post',
data
});
}
// ========== 产品需求 API ==========
const REQUIREMENT_PREFIX = `${WEB_SERVICE_PREFIX}/project/product/requirement`;
type RequirementResponse = Omit<
Api.Product.Requirement,
'id' | 'parentId' | 'moduleId' | 'proposerId' | 'currentHandlerUserId' | 'implementProjectId' | 'sourceBizId'
> & {
id: string | number;
parentId: string | number;
moduleId: string | number;
proposerId: string | number;
currentHandlerUserId?: string | number | null;
implementProjectId?: string | number | null;
implementProjectName?: string | null;
sourceBizId?: string | number | null;
children?: RequirementResponse[];
};
type RequirementPageResponse = Api.Product.PageResult<RequirementResponse>;
function normalizeRequirement(requirement: RequirementResponse): Api.Product.Requirement {
return {
...requirement,
id: normalizeStringId(requirement.id),
parentId: normalizeStringId(requirement.parentId),
moduleId: normalizeStringId(requirement.moduleId),
proposerId: normalizeStringId(requirement.proposerId),
currentHandlerUserId: normalizeNullableStringId(requirement.currentHandlerUserId),
implementProjectId: normalizeNullableStringId(requirement.implementProjectId),
implementProjectName: requirement.implementProjectName ?? null,
sourceBizId: normalizeNullableStringId(requirement.sourceBizId),
children: requirement.children?.map(normalizeRequirement)
};
}
/** 获取需求分页列表 */
export async function fetchGetRequirementPage(params?: Api.Product.RequirementSearchParams) {
const result = await request<RequirementPageResponse>({
...safeJsonRequestConfig,
url: `${REQUIREMENT_PREFIX}/page`,
method: 'get',
params
});
return mapServiceResult(result as ServiceRequestResult<RequirementPageResponse>, data => ({
...data,
list: data.list.map(normalizeRequirement)
}));
}
/** 获取需求树形列表支持分页pageSize只算父需求 */
export async function fetchGetRequirementTree(params?: Api.Product.RequirementSearchParams) {
const result = await request<Api.Product.PageResult<RequirementResponse>>({
...safeJsonRequestConfig,
url: `${REQUIREMENT_PREFIX}/tree`,
method: 'get',
params
});
return mapServiceResult(result as ServiceRequestResult<Api.Product.PageResult<RequirementResponse>>, data => ({
...data,
list: data.list.map(normalizeRequirement)
}));
}
/** 获取需求详情 */
export async function fetchGetRequirement(id: string, productId: string) {
const result = await request<RequirementResponse>({
...safeJsonRequestConfig,
url: `${REQUIREMENT_PREFIX}/get`,
method: 'get',
params: { id, productId }
});
return mapServiceResult(result as ServiceRequestResult<RequirementResponse>, normalizeRequirement);
}
/** 创建需求 */
export async function fetchCreateRequirement(data: Api.Product.SaveRequirementParams) {
const result = await request<string | number>({
...safeJsonRequestConfig,
url: `${REQUIREMENT_PREFIX}/create`,
method: 'post',
data
});
return mapServiceResult(result as ServiceRequestResult<string | number>, normalizeStringId);
}
/** 更新需求 */
export function fetchUpdateRequirement(data: Api.Product.UpdateRequirementParams) {
return request<boolean>({
...safeJsonRequestConfig,
url: `${REQUIREMENT_PREFIX}/update`,
method: 'put',
data
});
}
/** 变更需求状态 */
export function fetchChangeRequirementStatus(data: Api.Product.ChangeRequirementStatusParams) {
return request<boolean>({
...safeJsonRequestConfig,
url: `${REQUIREMENT_PREFIX}/change-status`,
method: 'post',
data
});
}
/** 删除需求 */
export function fetchDeleteRequirement(data: Api.Product.DeleteRequirementParams) {
return request<boolean>({
...safeJsonRequestConfig,
url: `${REQUIREMENT_PREFIX}/delete`,
method: 'post',
data
});
}
/** 拆分需求 */
export async function fetchSplitRequirement(data: Api.Product.SplitRequirementParams) {
const result = await request<string | number>({
...safeJsonRequestConfig,
url: `${REQUIREMENT_PREFIX}/split`,
method: 'post',
data
});
return mapServiceResult(result as ServiceRequestResult<string | number>, normalizeStringId);
}
/** 关闭需求 */
export function fetchCloseRequirement(data: Api.Product.CloseRequirementParams) {
return request<boolean>({
...safeJsonRequestConfig,
url: `${REQUIREMENT_PREFIX}/close`,
method: 'post',
data
});
}
/** 获取需求可执行的状态动作列表 */
export async function fetchGetRequirementAllowedTransitions(requirementId: string, productId: string) {
const result = await request<Api.Product.RequirementLifecycleAction[]>({
...safeJsonRequestConfig,
url: `${REQUIREMENT_PREFIX}/allowed-transitions`,
method: 'get',
params: { requirementId, productId }
});
return mapServiceResult(result as ServiceRequestResult<Api.Product.RequirementLifecycleAction[]>, data => data);
}
/** 获取需求生命周期信息 */
export async function fetchGetRequirementLifecycle(requirementId: string, productId: string) {
const result = await request<Api.Product.RequirementLifecycleInfo>({
...safeJsonRequestConfig,
url: `${REQUIREMENT_PREFIX}/lifecycle`,
method: 'get',
params: { requirementId, productId }
});
return mapServiceResult(result as ServiceRequestResult<Api.Product.RequirementLifecycleInfo>, data => data);
}
/** 获取需求所有状态字典 */
export async function fetchGetRequirementStatusDict() {
const result = await request<Api.Product.RequirementStatusDict[]>({
...safeJsonRequestConfig,
url: `${REQUIREMENT_PREFIX}/status/dict`,
method: 'get'
});
return mapServiceResult(result as ServiceRequestResult<Api.Product.RequirementStatusDict[]>, data => data);
}
/** 获取需求终止态状态字典 */
export async function fetchGetRequirementTerminalStatusDict() {
const result = await request<Api.Product.RequirementStatusDict[]>({
...safeJsonRequestConfig,
url: `${REQUIREMENT_PREFIX}/status/dict/terminal`,
method: 'get'
});
return mapServiceResult(result as ServiceRequestResult<Api.Product.RequirementStatusDict[]>, data => data);
}
// ========== 模块管理 API ==========
type RequirementModuleResponse = Omit<Api.Product.RequirementModule, 'id' | 'parentId' | 'productId'> & {
id: string | number;
parentId: string | number;
productId: string | number;
children?: RequirementModuleResponse[];
};
function normalizeRequirementModule(module: RequirementModuleResponse): Api.Product.RequirementModule {
return {
...module,
id: normalizeStringId(module.id),
parentId: normalizeStringId(module.parentId),
productId: normalizeStringId(module.productId),
children: module.children?.map(normalizeRequirementModule)
};
}
/** 获取需求模块树 */
export async function fetchGetRequirementModuleTree(productId: string) {
const result = await request<RequirementModuleResponse[]>({
...safeJsonRequestConfig,
url: `${REQUIREMENT_PREFIX}/module/tree`,
method: 'get',
params: { productId }
});
return mapServiceResult(result as ServiceRequestResult<RequirementModuleResponse[]>, data =>
data.map(normalizeRequirementModule)
);
}
/** 创建需求模块 */
export async function fetchCreateRequirementModule(data: Api.Product.SaveRequirementModuleParams) {
const result = await request<string | number>({
...safeJsonRequestConfig,
url: `${REQUIREMENT_PREFIX}/module/create`,
method: 'post',
data
});
return mapServiceResult(result as ServiceRequestResult<string | number>, normalizeStringId);
}
/** 更新需求模块 */
export function fetchUpdateRequirementModule(data: Api.Product.SaveRequirementModuleParams) {
return request<boolean>({
...safeJsonRequestConfig,
url: `${REQUIREMENT_PREFIX}/module/update`,
method: 'put',
data
});
}
/** 删除需求模块 */
export function fetchDeleteRequirementModule(data: Api.Product.DeleteRequirementModuleParams) {
return request<boolean>({
...safeJsonRequestConfig,
url: `${REQUIREMENT_PREFIX}/module/delete`,
method: 'post',
data
});
}
export async function fetchGetProductSettings(id: string) {
const result = await request<Api.Product.ProductSettings>({
...safeJsonRequestConfig,
url: `${PRODUCT_PREFIX}/${id}/settings`,
method: 'get'
});
return mapServiceResult(result as ServiceRequestResult<Api.Product.ProductSettings>, normalizeProductSettings);
}
export function fetchUpdateProductSettingBaseInfo(id: string, data: Api.Product.UpdateProductSettingBaseInfoParams) {
return request<boolean>({
...safeJsonRequestConfig,
url: `${PRODUCT_PREFIX}/${id}/settings/base-info`,
method: 'put',
data
});
}
export async function fetchGetProductMembers(id: string) {
const result = await request<Api.Product.ProductMember[]>({
...safeJsonRequestConfig,
url: `${PRODUCT_PREFIX}/${id}/members`,
method: 'get'
});
return mapServiceResult(result as ServiceRequestResult<Api.Product.ProductMember[]>, data =>
data.map(normalizeProductMember)
);
}
export async function fetchGetProductActivityTimelinePage(
id: string,
params: Api.Product.ProductActivityTimelinePageParams
) {
const query = createProductActivityTimelinePageQuery(params);
const url = query ? `${PRODUCT_PREFIX}/${id}/activities/page?${query}` : `${PRODUCT_PREFIX}/${id}/activities/page`;
const result = await request<ProductActivityTimelinePageResponse>({
...safeJsonRequestConfig,
url,
method: 'get'
});
return mapServiceResult(result as ServiceRequestResult<ProductActivityTimelinePageResponse>, data => ({
total: normalizePageTotal(data.total),
list: data.list.map(normalizeProductActivityTimelineItem)
}));
}
export async function fetchCreateProductMember(id: string, data: Api.Product.CreateProductMemberParams) {
const result = await request<string | number>({
...safeJsonRequestConfig,
url: `${PRODUCT_PREFIX}/${id}/members`,
method: 'post',
data
});
return mapServiceResult(result as ServiceRequestResult<string | number>, normalizeStringId);
}
export function fetchUpdateProductMember(id: string, memberId: string, data: Api.Product.UpdateProductMemberParams) {
return request<boolean>({
...safeJsonRequestConfig,
url: `${PRODUCT_PREFIX}/${id}/members/${memberId}`,
method: 'put',
data
});
}
export function fetchInactiveProductMember(
id: string,
memberId: string,
data: Api.Product.InactiveProductMemberParams
) {
return request<boolean>({
...safeJsonRequestConfig,
url: `${PRODUCT_PREFIX}/${id}/members/${memberId}/inactive`,
method: 'post',
data
});
}