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 & { id: string | number; managerUserId?: string | number | null; }; type ProductPageResponse = Api.Product.PageResult; 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, '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({ ...safeJsonRequestConfig, url: `${PRODUCT_PREFIX}/page`, method: 'get', params }); return mapServiceResult(result as ServiceRequestResult, data => ({ ...data, list: data.list.map(normalizeProduct) })); } /** 鑾峰彇浜у搧璇︽儏 */ export async function fetchGetProduct(id: string) { const result = await request({ ...safeJsonRequestConfig, url: `${PRODUCT_PREFIX}/get`, method: 'get', params: { id } }); return mapServiceResult(result as ServiceRequestResult, normalizeProduct); } /** 鍒涘缓浜у搧 */ export async function fetchCreateProduct(data: Api.Product.SaveProductParams) { const result = await request({ ...safeJsonRequestConfig, url: `${PRODUCT_PREFIX}/create`, method: 'post', data }); return mapServiceResult(result as ServiceRequestResult, normalizeStringId); } /** 鏇存柊浜у搧 */ export function fetchUpdateProduct(data: Api.Product.UpdateProductParams) { return request({ url: `${PRODUCT_PREFIX}/update`, method: 'put', data }); } /** 鍙樻洿浜у搧鐘舵€? */ export function fetchChangeProductStatus(data: Api.Product.ChangeProductStatusParams) { return request({ url: `${PRODUCT_PREFIX}/change-status`, method: 'post', data }); } /** 鍒犻櫎浜у搧 */ export function fetchDeleteProduct(data: Api.Product.DeleteProductParams) { return request({ url: `${PRODUCT_PREFIX}/delete`, method: 'post', data }); } export async function fetchGetProductSettings(id: string) { const result = await request({ ...safeJsonRequestConfig, url: `${PRODUCT_PREFIX}/${id}/settings`, method: 'get' }); return mapServiceResult(result as ServiceRequestResult, normalizeProductSettings); } export function fetchUpdateProductSettingBaseInfo(id: string, data: Api.Product.UpdateProductSettingBaseInfoParams) { return request({ ...safeJsonRequestConfig, url: `${PRODUCT_PREFIX}/${id}/settings/base-info`, method: 'put', data }); } export async function fetchGetProductMembers(id: string) { const result = await request({ ...safeJsonRequestConfig, url: `${PRODUCT_PREFIX}/${id}/members`, method: 'get' }); return mapServiceResult(result as ServiceRequestResult, 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({ ...safeJsonRequestConfig, url, method: 'get' }); return mapServiceResult(result as ServiceRequestResult, data => ({ total: normalizePageTotal(data.total), list: data.list.map(normalizeProductActivityTimelineItem) })); } export async function fetchCreateProductMember(id: string, data: Api.Product.CreateProductMemberParams) { const result = await request({ ...safeJsonRequestConfig, url: `${PRODUCT_PREFIX}/${id}/members`, method: 'post', data }); return mapServiceResult(result as ServiceRequestResult, normalizeStringId); } export function fetchUpdateProductMember(id: string, memberId: string, data: Api.Product.UpdateProductMemberParams) { return request({ ...safeJsonRequestConfig, url: `${PRODUCT_PREFIX}/${id}/members/${memberId}`, method: 'put', data }); } export function fetchInactiveProductMember( id: string, memberId: string, data: Api.Product.InactiveProductMemberParams ) { return request({ ...safeJsonRequestConfig, url: `${PRODUCT_PREFIX}/${id}/members/${memberId}/inactive`, method: 'post', data }); }