import { del, get, http, post, put, type JavaApiResponse, unwrapJavaResponse } from '@/shared/api/http' const JAVA_API_PREFIX = '/newApi/api' function getCurrentUserId() { const raw = typeof window === 'undefined' ? '' : window.localStorage.getItem('uid') || '' const value = Number(raw) if (!Number.isFinite(value) || value <= 0) { throw new Error('未获取到用户ID') } return value } export interface UploadedFileRef { fileKey: string originalFilename?: string relativePath?: string } export interface UploadFileVo { fileKey: string originalFilename: string localPath: string size: number relativePath?: string } export interface DedupeResultItem { resultId?: number sourceFilename: string outputFilename?: string success: boolean error?: string downloadUrl?: string } export interface DedupeRunVo { total: number successCount: number failedCount: number items: DedupeResultItem[] } export interface DedupeHistoryVo { items: DedupeResultItem[] } export interface DedupeRunRequest { files: UploadedFileRef[] selectedColumns: string[] keepIntegerIds: boolean keepUnderscoreIds: boolean keepIntegerMainIdsWhenNoSubIds: boolean archiveName?: string user_id: number } export interface SplitArchiveEntry { filename: string rowCount?: number } export interface SplitResultItem { resultId?: number sourceFilename: string outputFilename?: string success: boolean error?: string rowCount?: number downloadUrl?: string entryCount?: number entries?: SplitArchiveEntry[] } export interface SplitRunVo { total: number successCount: number failedCount: number items: SplitResultItem[] } export interface SplitHistoryVo { items: SplitResultItem[] } export interface SplitRunRequest { files: UploadedFileRef[] selectedColumns: string[] splitMode: 'rows_per_file' | 'parts' rowsPerFile?: number parts?: number archiveName?: string user_id: number } export interface ConvertResultItem { resultId?: number sourceFilename: string outputFilename?: string success: boolean error?: string downloadUrl?: string } export interface ConvertRunVo { total: number successCount: number failedCount: number items: ConvertResultItem[] } export interface ConvertHistoryVo { items: ConvertResultItem[] } export interface ConvertRunRequest { files: UploadedFileRef[] templateId: string archiveName?: string user_id: number } export interface DeleteBrandPreviewRow { rowIndex: number country: string asin: string status: string } export interface DeleteBrandCountryAsinItem { rowIndex: number asin: string status: string } export interface DeleteBrandCountryGroup { country: string asinCount: number items: DeleteBrandCountryAsinItem[] } export interface DeleteBrandCountryResultItem { asin: string status?: string } export interface DeleteBrandProcessedCountry { country: string items: DeleteBrandCountryResultItem[] } export interface DeleteBrandResultFile { fileKey?: string sourceFilename: string fileIndex?: number fileTotal?: number chunkIndex?: number chunkTotal?: number processedRows?: number totalRows?: number currentCountry?: string currentAsin?: string countries: DeleteBrandProcessedCountry[] } export interface DeleteBrandSubmitResultRequest { submissionId?: string files: DeleteBrandResultFile[] } export interface DeleteBrandLineProgressInfo { file_index?: number file_total?: number file_name?: string current_line?: number total_lines?: number current_country?: string current_asin?: string finished_files?: number phase?: string } export interface DeleteBrandLineProgress { has_progress: boolean info?: DeleteBrandLineProgressInfo } export interface DeleteBrandTaskItem { id: number taskNo?: string status?: string sourceFileCount?: number successFileCount?: number failedFileCount?: number errorMessage?: string createdAt?: string updatedAt?: string finishedAt?: string downloadUrl?: string downloadFilename?: string } export interface DeleteBrandTaskFileProgress { fileKey?: string sourceFilename?: string processedRows?: number totalRows?: number percent?: number status?: 'PENDING' | 'RUNNING' | 'COMPLETED' | 'FAILED' } export interface DeleteBrandTaskDetailVo { task: DeleteBrandTaskItem line_progress: DeleteBrandLineProgress items?: DeleteBrandResultItem[] fileProgress?: DeleteBrandTaskFileProgress[] } export interface DeleteBrandTaskBatchVo { items: DeleteBrandTaskDetailVo[] missingTaskIds: number[] } export type DeleteBrandMatchStatus = 'MATCHED' | 'PENDING' | 'CONFLICT' | 'INDEX_STALE' export interface DeleteBrandResultItem { resultId?: number fileKey?: string sourceFilename: string shopName?: string matched?: boolean matchStatus?: DeleteBrandMatchStatus matchMessage?: string shopId?: string platform?: string openStoreUrl?: string outputFilename?: string downloadUrl?: string taskId?: number countryCount?: number countries?: DeleteBrandCountryGroup[] totalRows?: number truncated?: boolean previewRows?: DeleteBrandPreviewRow[] success: boolean error?: string taskStatus?: string } export interface DeleteBrandRunVo { total: number successCount: number failedCount: number items: DeleteBrandResultItem[] } export interface DeleteBrandHistoryVo { items: DeleteBrandResultItem[] } export interface DeleteBrandRunRequest { files: UploadedFileRef[] user_id: number } export interface ConvertTemplateVo { id: string templateCode: string templateName: string outputFilename: string isDefault?: boolean builtIn?: boolean } export interface ConvertTemplateImportRequest { templateName: string templateContent: string } export interface ExcelInfoVo { headers: string[] totalRows: number } export function getExcelInfo(fileKey: string) { return unwrapJavaResponse(get>(`${JAVA_API_PREFIX}/files/excel-info`, { params: { fileKey }, })) } export function runDedupe(request: Omit | DedupeRunRequest) { return unwrapJavaResponse(post, DedupeRunRequest>(`${JAVA_API_PREFIX}/dedupe/run`, { ...request, user_id: getCurrentUserId(), })) } export function getDedupeHistory() { return unwrapJavaResponse(get>(`${JAVA_API_PREFIX}/dedupe/history`, { params: { user_id: getCurrentUserId() }, })) } export function deleteDedupeHistory(resultId: number) { return unwrapJavaResponse(del>(`${JAVA_API_PREFIX}/dedupe/history/${resultId}`, { params: { user_id: getCurrentUserId() }, })) } export function runSplit(request: Omit | SplitRunRequest) { return unwrapJavaResponse(post, SplitRunRequest>(`${JAVA_API_PREFIX}/split/run`, { ...request, user_id: getCurrentUserId(), })) } export function getSplitHistory() { return unwrapJavaResponse(get>(`${JAVA_API_PREFIX}/split/history`, { params: { user_id: getCurrentUserId() }, })) } export function deleteSplitHistory(resultId: number) { return unwrapJavaResponse(del>(`${JAVA_API_PREFIX}/split/history/${resultId}`, { params: { user_id: getCurrentUserId() }, })) } export function getConvertTemplates() { return unwrapJavaResponse(get>(`${JAVA_API_PREFIX}/convert/templates`)) } export function importConvertTemplate(request: ConvertTemplateImportRequest) { return unwrapJavaResponse( post, ConvertTemplateImportRequest>(`${JAVA_API_PREFIX}/convert/templates/import`, request), ) } export function setDefaultConvertTemplate(templateCode: string) { return unwrapJavaResponse(post>(`${JAVA_API_PREFIX}/convert/templates/${templateCode}/default`)) } export function deleteConvertTemplate(templateCode: string) { return unwrapJavaResponse(del>(`${JAVA_API_PREFIX}/convert/templates/${templateCode}`)) } export function runConvert(request: Omit | ConvertRunRequest) { return unwrapJavaResponse(post, ConvertRunRequest>(`${JAVA_API_PREFIX}/convert/run`, { ...request, user_id: getCurrentUserId(), })) } export function getConvertHistory() { return unwrapJavaResponse(get>(`${JAVA_API_PREFIX}/convert/history`, { params: { user_id: getCurrentUserId() }, })) } export function deleteConvertHistory(resultId: number) { return unwrapJavaResponse(del>(`${JAVA_API_PREFIX}/convert/history/${resultId}`, { params: { user_id: getCurrentUserId() }, })) } export function runDeleteBrand(request: Omit | DeleteBrandRunRequest) { return unwrapJavaResponse(post, DeleteBrandRunRequest>(`${JAVA_API_PREFIX}/delete-brand/run`, { ...request, user_id: getCurrentUserId(), })) } export function getDeleteBrandHistory() { return unwrapJavaResponse(get>(`${JAVA_API_PREFIX}/delete-brand/history`, { params: { user_id: getCurrentUserId() }, })) } export function deleteDeleteBrandHistory(resultId: number) { return unwrapJavaResponse(del>(`${JAVA_API_PREFIX}/delete-brand/history/${resultId}`, { params: { user_id: getCurrentUserId() }, })) } export function getDeleteBrandTaskDetail(taskId: number) { return unwrapJavaResponse(get>(`${JAVA_API_PREFIX}/delete-brand/tasks/${taskId}`)) } export function getDeleteBrandTaskDetails(taskIds: number[]) { return unwrapJavaResponse(post, { taskIds: number[] }>(`${JAVA_API_PREFIX}/delete-brand/tasks/batch`, { taskIds })) } export function getDeleteBrandTaskDownloadUrl(taskId: number) { return getJavaDownloadUrl(`/delete-brand/tasks/${taskId}/download`) } export function submitDeleteBrandResult(taskId: number, request: DeleteBrandSubmitResultRequest) { return unwrapJavaResponse(post, DeleteBrandSubmitResultRequest>(`${JAVA_API_PREFIX}/delete-brand/tasks/${taskId}/result`, request)) } /** 商品风险解决:备选店铺与匹配(推队列由前端 pywebview 完成) */ export interface ProductRiskCandidateVo { id: number shop_name: string created_at?: string } export interface ProductRiskShopQueueItem { shopName: string matched: boolean shopId?: string platform?: string companyName?: string openStoreUrl?: string matchedUserId?: number matchStatus?: string matchMessage?: string } export interface ProductRiskMatchShopsVo { items: ProductRiskShopQueueItem[] } export function listProductRiskCandidates() { return unwrapJavaResponse( get>(`${JAVA_API_PREFIX}/product-risk-resolve/candidates`, { params: { user_id: getCurrentUserId() }, }), ) } export function addProductRiskCandidate(shopName: string) { return unwrapJavaResponse( post, { user_id: number; shop_name: string }>( `${JAVA_API_PREFIX}/product-risk-resolve/candidates`, { user_id: getCurrentUserId(), shop_name: shopName }, ), ) } export function deleteProductRiskCandidate(id: number) { return unwrapJavaResponse( del>(`${JAVA_API_PREFIX}/product-risk-resolve/candidates/${id}`, { params: { user_id: getCurrentUserId() }, }), ) } export interface ProductRiskCountryPreferenceVo { country_codes: string[] } export function getProductRiskCountryPreference() { return unwrapJavaResponse( get>(`${JAVA_API_PREFIX}/product-risk-resolve/country-preference`, { params: { user_id: getCurrentUserId() }, }), ) } export function putProductRiskCountryPreference(countryCodes: string[]) { return unwrapJavaResponse( put< JavaApiResponse, { user_id: number; country_codes: string[] } >(`${JAVA_API_PREFIX}/product-risk-resolve/country-preference`, { user_id: getCurrentUserId(), country_codes: countryCodes, }), ) } export function matchProductRiskShops(shopNames: string[]) { return unwrapJavaResponse( post, { user_id: number; shop_names: string[] }>( `${JAVA_API_PREFIX}/product-risk-resolve/match-shops`, { user_id: getCurrentUserId(), shop_names: shopNames }, ), ) } export interface ProductRiskDashboardVo { candidateCount: number processedTaskCount: number successTaskCount: number failedTaskCount: number } export interface ProductRiskHistoryItem { resultId?: number taskId?: number shopName?: string shopId?: string platform?: string companyName?: string matched?: boolean matchStatus?: string matchMessage?: string taskStatus?: string success?: boolean error?: string outputFilename?: string downloadUrl?: string } export interface ProductRiskHistoryVo { items: ProductRiskHistoryItem[] } export interface ProductRiskTaskSummary { id?: number taskNo?: string status?: string errorMessage?: string createdAt?: string updatedAt?: string finishedAt?: string } export interface ProductRiskTaskDetailVo { task?: ProductRiskTaskSummary items?: ProductRiskHistoryItem[] } export interface ProductRiskTaskBatchVo { items: ProductRiskTaskDetailVo[] missingTaskIds?: number[] } export interface ProductRiskPendingDeleteVo { removed: boolean } export interface ProductRiskCreateTaskVo { taskId: number items: ProductRiskHistoryItem[] } export function getProductRiskDashboard() { return unwrapJavaResponse( get>(`${JAVA_API_PREFIX}/product-risk-resolve/dashboard`, { params: { user_id: getCurrentUserId() }, }), ) } export function getProductRiskHistory() { return unwrapJavaResponse( get>(`${JAVA_API_PREFIX}/product-risk-resolve/history`, { params: { user_id: getCurrentUserId() }, }), ) } export function deleteProductRiskHistory(resultId: number) { return unwrapJavaResponse( del>(`${JAVA_API_PREFIX}/product-risk-resolve/history/${resultId}`, { params: { user_id: getCurrentUserId() }, }), ) } export function createProductRiskTask(items: ProductRiskShopQueueItem[]) { return unwrapJavaResponse( post, { user_id: number; items: ProductRiskShopQueueItem[] }>( `${JAVA_API_PREFIX}/product-risk-resolve/tasks`, { user_id: getCurrentUserId(), items }, ), ) } export function deleteProductRiskTask(taskId: number) { return unwrapJavaResponse( del>(`${JAVA_API_PREFIX}/product-risk-resolve/tasks/${taskId}`, { params: { user_id: getCurrentUserId() }, }), ) } export function deletePendingProductRiskShopResult(shopName: string) { return unwrapJavaResponse( del>(`${JAVA_API_PREFIX}/product-risk-resolve/pending-shop-result`, { params: { user_id: getCurrentUserId(), shop_name: shopName }, }), ) } export function getProductRiskTasksBatch(taskIds: number[]) { return unwrapJavaResponse( post, { taskIds: number[] }>( `${JAVA_API_PREFIX}/product-risk-resolve/tasks/batch`, { taskIds }, ), ) } export function getProductRiskResultDownloadUrl(resultId: number) { return getJavaDownloadUrl(`/product-risk-resolve/results/${resultId}/download`) } export function getJavaDownloadUrl(path: string) { let raw = path.startsWith('http://') || path.startsWith('https://') ? path : `${JAVA_API_PREFIX}${path}` // 核心修复:pywebview 的 save_file_from_url 需要完整带 schema 的 URL if (!raw.startsWith('http://') && !raw.startsWith('https://') && typeof window !== 'undefined') { raw = `${window.location.origin}${raw}` } const separator = raw.includes('?') ? '&' : '?' return `${raw}${separator}user_id=${encodeURIComponent(String(getCurrentUserId()))}` } export { JAVA_API_PREFIX, http }