新需求更新 同步更新

This commit is contained in:
supernijia
2026-08-06 01:11:54 +08:00
parent 9048bbb7f8
commit 28e7fce11c
112 changed files with 7739 additions and 637 deletions
+36 -2
View File
@@ -2164,6 +2164,7 @@ export interface SimilarAsinParseVo {
groupCount?: number;
aiPrompt?: string;
imgSwitch?: boolean;
categorySwitch?: boolean;
items: SimilarAsinParsedRow[];
groups?: SimilarAsinParsedGroup[];
}
@@ -2222,16 +2223,28 @@ export interface SimilarAsinTaskBatchVo {
missingTaskIds?: number[];
}
export function parseSimilarAsin(files: UploadedFileRef[], apiKey?: string, imgSwitch = false) {
export function parseSimilarAsin(
files: UploadedFileRef[],
apiKey?: string,
imgSwitch = false,
categorySwitch = false,
) {
return unwrapJavaResponse(
post<
JavaApiResponse<SimilarAsinParseVo>,
{ user_id: number; files: UploadedFileRef[]; api_key?: string; img_switch: boolean }
{
user_id: number;
files: UploadedFileRef[];
api_key?: string;
img_switch: boolean;
category_switch: boolean;
}
>(`${JAVA_API_PREFIX}/similar-asin/parse`, {
user_id: getCurrentUserId(),
files,
api_key: apiKey,
img_switch: imgSwitch,
category_switch: categorySwitch,
}),
);
}
@@ -3078,6 +3091,16 @@ export interface CollectDataHistoryItem {
invalidFilteredCount?: number;
brandRejectedCount?: number;
finalRowCount?: number;
totalRows?: number;
receivedRows?: number;
processedRows?: number;
collectStage?: string;
currentKeyword?: string;
searchCurrentPage?: number;
searchTotalPages?: number;
detailProcessedAsins?: number;
detailTotalAsins?: number;
progressPercent?: number;
createdAt?: string;
startedAt?: string;
finishedAt?: string;
@@ -3246,6 +3269,17 @@ export function putCollectDataCountryPreference(countryCodes: string[]) {
);
}
export function failCollectDataTask(taskId: number, error?: string) {
const params = new URLSearchParams({ user_id: String(getCurrentUserId()) });
if (error) params.set('error', error);
return unwrapJavaResponse(
post<JavaApiResponse<null>, undefined>(
`${JAVA_API_PREFIX}/collect-data/tasks/${taskId}/fail?${params.toString()}`,
undefined,
),
);
}
// ========== 上架 ==========
export interface PublishSourceFile {
@@ -0,0 +1,13 @@
import { getJavaDownloadUrl } from '@/shared/api/java-modules'
export type ModuleTemplateCode =
| 'publish'
| 'delete-brand'
| 'appearance-patent'
| 'price-track'
| 'collect-data'
| 'similar-asin'
export function getModuleTemplateDownloadUrl(moduleCode: ModuleTemplateCode) {
return getJavaDownloadUrl(`/module-templates/${encodeURIComponent(moduleCode)}/download`)
}
@@ -0,0 +1,159 @@
<template>
<div class="module-template-download">
<button
type="button"
class="module-template-download__button"
:disabled="downloading"
:aria-label="`下载文件模板:${filename}`"
:title="`下载 ${filename}`"
@click="downloadTemplate"
>
<span class="module-template-download__badge" aria-hidden="true">XLSX</span>
<span class="module-template-download__copy">
<strong>{{ downloading ? '正在下载...' : '下载文件模板' }}</strong>
<span>{{ filename }}</span>
</span>
<span class="module-template-download__icon" aria-hidden="true"></span>
</button>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
import {
getModuleTemplateDownloadUrl,
type ModuleTemplateCode,
} from '@/shared/api/module-templates'
import { getPywebviewApi } from '@/shared/bridges/pywebview'
import { saveUrlWithProgress } from '@/shared/utils/download-progress'
const props = defineProps<{
moduleCode: ModuleTemplateCode
filename: string
}>()
const downloading = ref(false)
async function downloadInBrowser(url: string) {
const response = await fetch(url)
if (!response.ok) {
throw new Error(`模板下载失败(HTTP ${response.status}`)
}
const objectUrl = URL.createObjectURL(await response.blob())
const link = document.createElement('a')
link.href = objectUrl
link.download = props.filename
link.style.display = 'none'
document.body.appendChild(link)
link.click()
link.remove()
window.setTimeout(() => URL.revokeObjectURL(objectUrl), 0)
}
async function downloadTemplate() {
downloading.value = true
try {
const url = getModuleTemplateDownloadUrl(props.moduleCode)
const api = getPywebviewApi()
if (!api?.save_file_from_url_new) {
await downloadInBrowser(url)
return
}
const result = await saveUrlWithProgress(url, props.filename)
if (result.success) {
ElMessage.success(`已保存:${result.path || props.filename}`)
} else if (result.error && result.error !== '用户取消') {
ElMessage.error(result.error)
}
} catch (error) {
ElMessage.error(error instanceof Error ? error.message : '模板下载失败')
} finally {
downloading.value = false
}
}
</script>
<style scoped>
.module-template-download {
flex: 0 0 auto;
margin-top: auto;
padding-top: 20px;
}
.module-template-download__button {
display: grid;
grid-template-columns: auto minmax(0, 1fr) auto;
align-items: center;
width: 100%;
min-height: 64px;
padding: 11px 12px;
gap: 11px;
border: 1px solid #3a424c;
border-radius: 6px;
background: #252a31;
color: #e5e7eb;
text-align: left;
cursor: pointer;
transition: border-color 0.15s ease, background-color 0.15s ease;
}
.module-template-download__button:hover:not(:disabled) {
border-color: #4f8fbc;
background: #29323b;
}
.module-template-download__button:focus-visible {
outline: 2px solid rgba(96, 165, 250, 0.9);
outline-offset: 2px;
}
.module-template-download__button:disabled {
cursor: wait;
opacity: 0.65;
}
.module-template-download__badge {
display: inline-flex;
align-items: center;
justify-content: center;
width: 42px;
height: 28px;
border-radius: 4px;
background: #1f6f4a;
color: #f0fdf4;
font-size: 10px;
font-weight: 700;
letter-spacing: 0;
}
.module-template-download__copy {
display: flex;
min-width: 0;
flex-direction: column;
gap: 3px;
}
.module-template-download__copy strong {
color: #f3f4f6;
font-size: 13px;
font-weight: 600;
line-height: 1.35;
}
.module-template-download__copy span {
color: #9ca3af;
font-size: 11px;
line-height: 1.35;
overflow-wrap: anywhere;
}
.module-template-download__icon {
color: #7dd3fc;
font-size: 22px;
line-height: 1;
}
</style>