处理后台管理系统、修复BUG、处理权限

This commit is contained in:
super
2026-04-22 01:09:28 +08:00
parent d691e53886
commit 236b73755c
77 changed files with 5157 additions and 522 deletions

View File

@@ -7,8 +7,16 @@
type JavaApiResponse,
unwrapJavaResponse,
} from "@/shared/api/http";
import { getTaskProgressCacheTtlMs } from "@/shared/task-progress-config";
const JAVA_API_PREFIX = "/newApi/api";
type TaskProgressCacheEntry = {
expiresAt: number;
data: unknown;
};
const taskProgressResponseCache = new Map<string, TaskProgressCacheEntry>();
const taskProgressInflightRequests = new Map<string, Promise<unknown>>();
function getCurrentUserId() {
const raw =
@@ -22,6 +30,56 @@ function getCurrentUserId() {
return value;
}
function normalizeTaskIds(taskIds: number[]) {
return Array.from(
new Set(
(taskIds || [])
.map((taskId) => Number(taskId))
.filter((taskId) => Number.isFinite(taskId) && taskId > 0),
),
).sort((left, right) => left - right);
}
function buildTaskProgressRequestKey(path: string, taskIds: number[]) {
return `${path}::${taskIds.join(",")}`;
}
async function postTaskProgressBatch<T>(path: string, taskIds: number[]) {
const normalizedTaskIds = normalizeTaskIds(taskIds);
if (!normalizedTaskIds.length) {
return { items: [], missingTaskIds: [] } as T;
}
const cacheKey = buildTaskProgressRequestKey(path, normalizedTaskIds);
const now = Date.now();
const cached = taskProgressResponseCache.get(cacheKey);
if (cached && cached.expiresAt > now) {
return cached.data as T;
}
const inflight = taskProgressInflightRequests.get(cacheKey);
if (inflight) {
return (await inflight) as T;
}
const requestPromise = unwrapJavaResponse(
post<JavaApiResponse<T>, { taskIds: number[] }>(path, { taskIds: normalizedTaskIds }),
)
.then((data) => {
taskProgressResponseCache.set(cacheKey, {
data,
expiresAt: Date.now() + getTaskProgressCacheTtlMs(),
});
return data;
})
.finally(() => {
taskProgressInflightRequests.delete(cacheKey);
});
taskProgressInflightRequests.set(cacheKey, requestPromise);
return requestPromise;
}
export interface UploadedFileRef {
fileKey: string;
originalFilename?: string;
@@ -916,6 +974,221 @@ export function getShopMatchResultDownloadUrl(resultId: number) {
return getJavaDownloadUrl(`/shop-match/results/${resultId}/download`);
}
export type PatrolDeleteCandidateVo = ProductRiskCandidateVo;
export type PatrolDeleteDashboardVo = ProductRiskDashboardVo;
export type PatrolDeleteShopQueueItem = ProductRiskShopQueueItem;
export interface PatrolDeleteCountryMetricRow {
status: string;
quantity: string;
deleteQuantity: string;
processStatus: string;
}
export interface PatrolDeleteCountrySection {
country: string;
rows: PatrolDeleteCountryMetricRow[];
}
export interface PatrolDeleteCartRatio {
country: string;
ratio: string;
}
export interface PatrolDeleteTaskItem {
shopName?: string;
matched?: boolean;
shopId?: string;
platform?: string;
companyName?: string;
matchStatus?: string;
matchMessage?: string;
countrySections: PatrolDeleteCountrySection[];
cartRatios: PatrolDeleteCartRatio[];
}
export interface PatrolDeleteHistoryItem {
resultId?: number;
taskId?: number;
shopName?: string;
shopId?: string;
platform?: string;
companyName?: string;
matched?: boolean;
matchStatus?: string;
matchMessage?: string;
taskStatus?: string;
success?: boolean;
error?: string;
createdAt?: string;
finishedAt?: string;
outputFilename?: string;
downloadUrl?: string;
countrySections: PatrolDeleteCountrySection[];
cartRatios: PatrolDeleteCartRatio[];
}
export interface PatrolDeleteHistoryVo {
items: PatrolDeleteHistoryItem[];
}
export interface PatrolDeleteTaskBatchVo {
items: PatrolDeleteHistoryItem[];
missingTaskIds: number[];
}
export interface PatrolDeleteCreateTaskVo {
taskId: number;
items: PatrolDeleteHistoryItem[];
}
export function listPatrolDeleteCandidates() {
return unwrapJavaResponse(
get<JavaApiResponse<PatrolDeleteCandidateVo[]>>(
`${JAVA_API_PREFIX}/patrol-delete/candidates`,
{
params: { user_id: getCurrentUserId() },
},
),
);
}
export function addPatrolDeleteCandidate(shopName: string) {
return unwrapJavaResponse(
post<
JavaApiResponse<PatrolDeleteCandidateVo>,
{ user_id: number; shop_name: string }
>(`${JAVA_API_PREFIX}/patrol-delete/candidates`, {
user_id: getCurrentUserId(),
shop_name: shopName,
}),
);
}
export function deletePatrolDeleteCandidate(id: number) {
return unwrapJavaResponse(
del<JavaApiResponse<null>>(
`${JAVA_API_PREFIX}/patrol-delete/candidates/${id}`,
{
params: { user_id: getCurrentUserId() },
},
),
);
}
export function matchPatrolDeleteShops(shopNames: string[]) {
return unwrapJavaResponse(
post<
JavaApiResponse<ProductRiskMatchShopsVo>,
{ user_id: number; shop_names: string[] }
>(`${JAVA_API_PREFIX}/patrol-delete/match-shops`, {
user_id: getCurrentUserId(),
shop_names: shopNames,
}),
);
}
export function getPatrolDeleteDashboard() {
return unwrapJavaResponse(
get<JavaApiResponse<PatrolDeleteDashboardVo>>(
`${JAVA_API_PREFIX}/patrol-delete/dashboard`,
{
params: { user_id: getCurrentUserId() },
},
),
);
}
export function getPatrolDeleteHistory() {
return unwrapJavaResponse(
get<JavaApiResponse<PatrolDeleteHistoryVo>>(
`${JAVA_API_PREFIX}/patrol-delete/history`,
{
params: { user_id: getCurrentUserId() },
},
),
);
}
export function getPatrolDeleteTaskProgressBatch(taskIds: number[]) {
return postTaskProgressBatch<PatrolDeleteTaskBatchVo>(
`${JAVA_API_PREFIX}/patrol-delete/tasks/progress/batch`,
taskIds,
);
}
export function createPatrolDeleteTask(items: PatrolDeleteTaskItem[]) {
return unwrapJavaResponse(
post<
JavaApiResponse<PatrolDeleteCreateTaskVo>,
{ user_id: number; items: PatrolDeleteTaskItem[] }
>(`${JAVA_API_PREFIX}/patrol-delete/tasks`, {
user_id: getCurrentUserId(),
items,
}),
);
}
export function submitPatrolDeleteTaskResult(
taskId: number,
payload: {
shops: Array<{
shopName: string;
error?: string;
countrySections: PatrolDeleteCountrySection[];
cartRatios: PatrolDeleteCartRatio[];
shopDone?: boolean;
submissionId?: string;
chunkIndex?: number;
chunkTotal?: number;
}>;
},
) {
return unwrapJavaResponse(
post<
JavaApiResponse<null>,
{
shops: Array<{
shopName: string;
error?: string;
countrySections: PatrolDeleteCountrySection[];
cartRatios: PatrolDeleteCartRatio[];
shopDone?: boolean;
submissionId?: string;
chunkIndex?: number;
chunkTotal?: number;
}>;
}
>(`${JAVA_API_PREFIX}/patrol-delete/tasks/${taskId}/result`, payload),
);
}
export function getPatrolDeleteResultDownloadUrl(resultId: number) {
return getJavaDownloadUrl(`/patrol-delete/results/${resultId}/download`);
}
export function deletePatrolDeleteTask(taskId: number) {
return unwrapJavaResponse(
del<JavaApiResponse<null>>(
`${JAVA_API_PREFIX}/patrol-delete/tasks/${taskId}`,
{
params: { user_id: getCurrentUserId() },
},
),
);
}
export function deletePatrolDeleteHistory(resultId: number) {
return unwrapJavaResponse(
del<JavaApiResponse<null>>(
`${JAVA_API_PREFIX}/patrol-delete/history/${resultId}`,
{
params: { user_id: getCurrentUserId() },
},
),
);
}
// ========== 跟价 ==========
export interface PriceTrackCandidateVo {
@@ -1095,29 +1368,23 @@ export function matchPriceTrackShops(
}
export function getShopMatchTaskProgressBatch(taskIds: number[]) {
return unwrapJavaResponse(
post<JavaApiResponse<ShopMatchTaskBatchVo>, { taskIds: number[] }>(
`${JAVA_API_PREFIX}/shop-match/tasks/progress/batch`,
{ taskIds },
),
return postTaskProgressBatch<ShopMatchTaskBatchVo>(
`${JAVA_API_PREFIX}/shop-match/tasks/progress/batch`,
taskIds,
);
}
export function getProductRiskTaskProgressBatch(taskIds: number[]) {
return unwrapJavaResponse(
post<JavaApiResponse<ProductRiskTaskBatchVo>, { taskIds: number[] }>(
`${JAVA_API_PREFIX}/product-risk-resolve/tasks/progress/batch`,
{ taskIds },
),
return postTaskProgressBatch<ProductRiskTaskBatchVo>(
`${JAVA_API_PREFIX}/product-risk-resolve/tasks/progress/batch`,
taskIds,
);
}
export function getDeleteBrandTaskProgress(taskIds: number[]) {
return unwrapJavaResponse(
post<JavaApiResponse<DeleteBrandTaskBatchVo>, { taskIds: number[] }>(
`${JAVA_API_PREFIX}/delete-brand/tasks/progress/batch`,
{ taskIds },
),
return postTaskProgressBatch<DeleteBrandTaskBatchVo>(
`${JAVA_API_PREFIX}/delete-brand/tasks/progress/batch`,
taskIds,
);
}
@@ -1268,11 +1535,9 @@ export function stopPriceTrackLoopRun(loopRunId: number) {
}
export function getPriceTrackTaskProgressBatch(taskIds: number[]) {
return unwrapJavaResponse(
post<JavaApiResponse<PriceTrackTaskBatchVo>, { taskIds: number[] }>(
`${JAVA_API_PREFIX}/price-track/tasks/progress/batch`,
{ taskIds },
),
return postTaskProgressBatch<PriceTrackTaskBatchVo>(
`${JAVA_API_PREFIX}/price-track/tasks/progress/batch`,
taskIds,
);
}