From f9d1848280bdc52c83290af0e98ab7d1e3f49c1f Mon Sep 17 00:00:00 2001 From: zhangzijienbplus <17738440858@163.com> Date: Fri, 14 Nov 2025 17:22:25 +0800 Subject: [PATCH] =?UTF-8?q?feat(amazon):=E4=BC=98=E5=8C=96=E5=95=86?= =?UTF-8?q?=E6=A0=87=E7=AD=9B=E6=9F=A5=E9=87=8D=E8=AF=95=E6=9C=BA=E5=88=B6?= =?UTF-8?q?=E5=92=8C=E8=BF=9B=E5=BA=A6=E6=98=BE=E7=A4=BA-=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E9=98=B2=E6=8A=96=E6=8E=A7=E5=88=B6=EF=BC=8C=E9=81=BF?= =?UTF-8?q?=E5=85=8D=E9=A2=91=E7=B9=81=E7=82=B9=E5=87=BB=E9=87=8D=E8=AF=95?= =?UTF-8?q?=E6=8C=89=E9=92=AE=20-=20=E4=BC=98=E5=8C=96=E9=87=8D=E8=AF=95?= =?UTF-8?q?=E9=80=BB=E8=BE=91=EF=BC=8C=E5=A2=9E=E5=8A=A0=E6=97=B6=E9=97=B4?= =?UTF-8?q?=E9=97=B4=E9=9A=94=E9=99=90=E5=88=B6=E5=92=8C=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E6=A3=80=E6=9F=A5=20-=20=E7=A7=BB=E9=99=A4=E8=A1=A8=E6=A0=BC?= =?UTF-8?q?=E4=B8=8A=E6=96=B9=E5=86=97=E4=BD=99=E7=9A=84=E8=BF=9B=E5=BA=A6?= =?UTF-8?q?=E6=9D=A1=E6=98=BE=E7=A4=BA=20-=20=E6=9B=B4=E6=96=B0=E5=8F=96?= =?UTF-8?q?=E6=B6=88=E7=8A=B6=E6=80=81=E4=B8=8B=E7=9A=84=E6=8F=90=E7=A4=BA?= =?UTF-8?q?=E6=96=87=E6=A1=88=E5=92=8C=E6=93=8D=E4=BD=9C=E5=BC=95=E5=AF=BC?= =?UTF-8?q?-=20=E4=BF=AE=E5=A4=8D=E5=93=81=E7=89=8C=E7=BB=9F=E8=AE=A1?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=98=BE=E7=A4=BA=E9=80=BB=E8=BE=91=EF=BC=8C?= =?UTF-8?q?=E7=A1=AE=E4=BF=9D=E5=87=86=E7=A1=AE=E6=80=A7-=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E7=94=A8=E6=88=B7=E7=95=8C=E9=9D=A2=E5=85=83=E7=B4=A0?= =?UTF-8?q?=E9=97=B4=E8=B7=9D=E5=92=8C=E6=A0=B7=E5=BC=8F=E7=BB=86=E8=8A=82?= =?UTF-8?q?=20-=20=E5=AE=8C=E5=96=84=E5=90=8E=E7=AB=AF=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E8=B0=83=E7=94=A8=EF=BC=8C=E6=94=AF=E6=8C=81=E4=BF=A1=E5=8F=B7?= =?UTF-8?q?=E4=B8=AD=E6=96=AD=E5=92=8C=E9=94=99=E8=AF=AF=E5=A4=84=E7=90=86?= =?UTF-8?q?=20-=E4=BC=98=E5=8C=96SSE=E8=BF=9E=E6=8E=A5=E7=AE=A1=E7=90=86?= =?UTF-8?q?=EF=BC=8C=E9=98=B2=E6=AD=A2=E8=BF=9E=E6=8E=A5=E6=B3=84=E6=BC=8F?= =?UTF-8?q?=20-=20=E6=94=B9=E8=BF=9B=E4=BB=BB=E5=8A=A1=E5=8F=96=E6=B6=88?= =?UTF-8?q?=E6=9C=BA=E5=88=B6=EF=BC=8C=E6=8F=90=E5=8D=87=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E4=BD=93=E9=AA=8C=20-=20=E6=9B=B4=E6=96=B0=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E5=B1=95=E7=A4=BA=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E6=B3=A8=E5=86=8C=E6=97=B6=E9=97=B4=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- electron-vue-template/src/main/main.ts | 17 +- electron-vue-template/src/renderer/App.vue | 33 +- .../src/renderer/api/http.ts | 2 +- .../src/renderer/api/mark.ts | 24 +- .../components/amazon/AmazonDashboard.vue | 52 +- .../components/amazon/AsinQueryPanel.vue | 2 +- .../components/amazon/TrademarkCheckPanel.vue | 1097 +++++++++++------ .../tashow/erp/config/JavaBridgeConfig.java | 13 - .../erp/controller/TrademarkController.java | 258 +++- .../tashow/erp/fx/controller/JavaBridge.java | 79 -- .../com/tashow/erp/test/UsptoApiTest.java | 4 +- .../java/com/tashow/erp/utils/ProxyPool.java | 31 +- .../tashow/erp/utils/TrademarkCheckUtil.java | 263 ++-- .../monitor/ClientAccountController.java | 9 +- .../controller/system/SysLoginController.java | 2 - 15 files changed, 1245 insertions(+), 641 deletions(-) delete mode 100644 erp_client_sb/src/main/java/com/tashow/erp/config/JavaBridgeConfig.java delete mode 100644 erp_client_sb/src/main/java/com/tashow/erp/fx/controller/JavaBridge.java diff --git a/electron-vue-template/src/main/main.ts b/electron-vue-template/src/main/main.ts index 4ac6a56..450edd5 100644 --- a/electron-vue-template/src/main/main.ts +++ b/electron-vue-template/src/main/main.ts @@ -229,8 +229,6 @@ function startSpringBoot() { const dataDir = getDataDirectoryPath(); const logDir = getLogDirectoryPath(); const logbackConfigPath = getLogbackConfigPath(); - console.log('[Spring Boot] JAR路径:', jarPath); - console.log('[Spring Boot] Java路径:', javaPath); if (!existsSync(jarPath)) { dialog.showErrorBox('启动失败', `JAR 文件不存在:\n${jarPath}`); app.quit(); @@ -475,9 +473,14 @@ app.whenReady().then(() => { splashWindow.once('ready-to-show', () => splashWindow?.show()); } + // 已手动启动后端 setTimeout(() => { startSpringBoot(); }, 200); + + // setTimeout(() => { + // openAppIfNotOpened(); + // }, 200); app.on('activate', () => { if (mainWindow && !mainWindow.isDestroyed()) { @@ -856,15 +859,7 @@ ipcMain.handle('dev-skip-backend', () => { return { success: false, error: '仅开发模式可用' }; }); -// 开发模式:手动启动后端 -ipcMain.handle('dev-start-backend', () => { - if (isDev) { - console.log('[开发模式] 前端请求启动后端'); - startSpringBoot(); - return { success: true }; - } - return { success: false, error: '仅开发模式可用' }; -}); + // 窗口控制 API ipcMain.handle('window-minimize', () => { diff --git a/electron-vue-template/src/renderer/App.vue b/electron-vue-template/src/renderer/App.vue index 3c98a24..e615ab0 100644 --- a/electron-vue-template/src/renderer/App.vue +++ b/electron-vue-template/src/renderer/App.vue @@ -51,6 +51,7 @@ const showAuthDialog = ref(false) const showRegDialog = ref(false) const zhCnLocale = zhCn const currentUsername = ref('') +const registerTime = ref('') const showDeviceDialog = ref(false) const deviceLoading = ref(false) const devices = ref([]) @@ -220,6 +221,7 @@ async function handleLoginSuccess(data: { vipExpireTime.value = data.expireTime ? new Date(data.expireTime) : null accountType.value = data.accountType || 'trial' deviceTrialExpired.value = data.deviceTrialExpired || false + registerTime.value = data.registerTime || '' const deviceId = await getOrCreateDeviceId() await deviceApi.register({ @@ -249,6 +251,7 @@ async function clearLocalAuth() { removeToken() isAuthenticated.value = false currentUsername.value = '' + registerTime.value = '' userPermissions.value = '' vipExpireTime.value = null deviceTrialExpired.value = false @@ -319,6 +322,7 @@ async function checkAuth() { userPermissions.value = res.data.permissions || '' deviceTrialExpired.value = res.data.deviceTrialExpired || false accountType.value = res.data.accountType || 'trial' + registerTime.value = res.data.registerTime || '' if (res.data.expireTime) { vipExpireTime.value = new Date(res.data.expireTime) @@ -640,15 +644,8 @@ onUnmounted(() => {
用户头像 - 默认头像
@@ -657,7 +654,7 @@ onUnmounted(() => { {{ isAuthenticated ? currentUsername : '登录/注册' }} VIP {{ vipStatus.daysLeft }}天
-
{{ isAuthenticated ? '18659156151' : '登录账号体验完整功能' }}
+
{{ isAuthenticated ? ` ${registerTime ? registerTime.replace('T', ' ').substring(0, 16) : '未知'}` : '登录账号体验完整功能' }}
@@ -903,7 +900,6 @@ onUnmounted(() => { /* 主Logo */ .main-logo { - display: flex; align-items: center; justify-content: center; padding: 8px 0; @@ -929,8 +925,8 @@ onUnmounted(() => { .avatar-wrapper { flex-shrink: 0; - width: 44px; - height: 44px; + width: 40px; + height: 40px; border-radius: 50%; overflow: hidden; background: #fff; @@ -958,7 +954,7 @@ onUnmounted(() => { .user-name-wrapper { display: flex; align-items: center; - gap: 6px; + gap: 4px; min-width: 0; } @@ -968,15 +964,17 @@ onUnmounted(() => { color: #303133; white-space: nowrap; line-height: 1.2; - flex-shrink: 0; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; } .vip-badge { display: inline-flex; align-items: center; justify-content: center; - padding: 0px 5px; - height: 16px; + padding: 0px 3px; + height: 14px; background: #BAE0FF; border: 1px solid rgba(22, 119, 255, 0.05); border-radius: 8px; @@ -1021,7 +1019,8 @@ onUnmounted(() => { .brand-logo { max-width: 100%; max-height: 100%; - object-fit: contain; + object-fit: cover; + border-radius: 12px; } .menu { diff --git a/electron-vue-template/src/renderer/api/http.ts b/electron-vue-template/src/renderer/api/http.ts index 249dbf8..8084ec7 100644 --- a/electron-vue-template/src/renderer/api/http.ts +++ b/electron-vue-template/src/renderer/api/http.ts @@ -1,6 +1,6 @@ export type HttpMethod = 'GET' | 'POST' | 'DELETE'; const RUOYI_BASE = 'http://8.138.23.49:8085'; -// const RUOYI_BASE = 'http://192.168.1.89:8085'; + // const RUOYI_BASE = 'http://192.168.1.89:8085'; export const CONFIG = { CLIENT_BASE: 'http://localhost:8081', RUOYI_BASE, diff --git a/electron-vue-template/src/renderer/api/mark.ts b/electron-vue-template/src/renderer/api/mark.ts index 97f5ab7..6086842 100644 --- a/electron-vue-template/src/renderer/api/mark.ts +++ b/electron-vue-template/src/renderer/api/mark.ts @@ -2,28 +2,28 @@ import { http } from './http' export const markApi = { // 新建任务(调用 erp_client_sb) - newTask(file: File) { + newTask(file: File, signal?: AbortSignal) { const formData = new FormData() formData.append('file', file) - return http.upload<{ code: number, data: any, msg: string }>('/api/trademark/newTask', formData) + return http.upload<{ code: number, data: any, msg: string }>('/api/trademark/newTask', formData, signal) }, // 获取任务列表及筛选数据(调用 erp_client_sb) - getTask() { - return http.post<{ - code: number, - data: { - original: any, + getTask(signal?: AbortSignal) { + return http.post<{ + code: number, + data: { + original: any, filtered: Record[], // 完整的行数据(Map格式) headers: string[] // 表头 - }, - msg: string - }>('/api/trademark/task') + }, + msg: string + }>('/api/trademark/task', undefined, signal) }, // 品牌商标筛查 - brandCheck(brands: string[], taskId?: string) { - return http.post<{ code: number, data: { total: number, checked: number, registered: number, unregistered: number, failed: number, data: any[], duration: string }, msg: string }>('/api/trademark/brandCheck', { brands, taskId }) + brandCheck(brands: string[], taskId?: string, signal?: AbortSignal) { + return http.post<{ code: number, data: { total: number, checked: number, registered: number, unregistered: number, failed: number, data: any[], duration: string }, msg: string }>('/api/trademark/brandCheck', { brands, taskId }, signal) }, // 查询品牌筛查进度 diff --git a/electron-vue-template/src/renderer/components/amazon/AmazonDashboard.vue b/electron-vue-template/src/renderer/components/amazon/AmazonDashboard.vue index 40e988f..12ce93e 100644 --- a/electron-vue-template/src/renderer/components/amazon/AmazonDashboard.vue +++ b/electron-vue-template/src/renderer/components/amazon/AmazonDashboard.vue @@ -107,10 +107,28 @@ function handleCancelTask() { } } +const isRetrying = ref(false) +let lastRetryTime = 0 + function handleRetryTask() { + const now = Date.now() + if (now - lastRetryTime < 3000 || isRetrying.value || loading.value || trademarkPanelRef.value?.trademarkLoading) { + return + } + + lastRetryTime = now + isRetrying.value = true + if (trademarkPanelRef.value && typeof trademarkPanelRef.value.startTrademarkQuery === 'function') { trademarkPanelRef.value.startTrademarkQuery() } + + const checkInterval = setInterval(() => { + if (trademarkPanelRef.value?.trademarkLoading || Date.now() - now > 2000) { + clearInterval(checkInterval) + isRetrying.value = false + } + }, 50) } function openSubscribeDialog() { @@ -176,19 +194,6 @@ function handleExportData() {
- -
-
-
-
-
-
-
-
{{ progressPercentage }}%
-
-
-
-
@@ -276,15 +281,14 @@ function handleExportData() {
-
@@ -429,11 +433,11 @@ function handleExportData() {
未注册 - {{ trademarkPanelRef?.isBrandTaskRealData ? trademarkPanelRef.taskProgress.brand.completed : '-' }} + {{ trademarkPanelRef?.brandStatsDisplay?.unregistered || '-' }}
已注册 - {{ trademarkPanelRef?.isBrandTaskRealData ? (trademarkPanelRef.taskProgress.brand.total - trademarkPanelRef.taskProgress.brand.completed) : '-' }} + {{ trademarkPanelRef?.brandStatsDisplay?.registered || '-' }}
@@ -702,13 +706,6 @@ function handleExportData() { .text:focus { border-color: #409EFF; } .text:disabled { background: #f5f7fa; color: #c0c4cc; } .action-buttons { display: flex; gap: 10px; flex-wrap: wrap; } -.progress-section { margin: 0px 12px 0px 12px; } -.progress-head { margin-bottom: 8px; } -.progress-box { padding: 4px 0; } -.progress-container { display: flex; align-items: center; gap: 8px; } -.progress-bar { flex: 1; height: 6px; background: #e3eeff; border-radius: 999px; overflow: hidden; } -.progress-fill { height: 100%; background: #1677FF; border-radius: 999px; transition: width 0.3s ease; } -.progress-text { font-size: 13px; color: #1677FF; font-weight: 500; min-width: 44px; text-align: right; } .current-status { font-size: 12px; color: #606266; padding-left: 2px; } .table-container { display: flex; @@ -970,6 +967,7 @@ function handleExportData() { width: 48px; height: 48px; } + .done-banner .banner-icon { background: transparent; } diff --git a/electron-vue-template/src/renderer/components/amazon/AsinQueryPanel.vue b/electron-vue-template/src/renderer/components/amazon/AsinQueryPanel.vue index afcff14..37891a4 100644 --- a/electron-vue-template/src/renderer/components/amazon/AsinQueryPanel.vue +++ b/electron-vue-template/src/renderer/components/amazon/AsinQueryPanel.vue @@ -365,7 +365,7 @@ defineExpose({ .step-header { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; } .title { font-size: 14px; font-weight: 600; color: #303133; text-align: left; } .desc { font-size: 12px; color: #909399; margin-bottom: 10px; text-align: left; line-height: 1.5; } -.links { display: flex; align-items: center; gap: 6px; margin-bottom: 8px; } +.links { display: flex; align-items: center; gap: 2px; margin-bottom: 8px; } .link { color: #409EFF; cursor: pointer; font-size: 12px; } .sep { color: #dcdfe6; } .dropzone { border: 1px dashed #c0c4cc; border-radius: 6px; padding: 16px; text-align: center; cursor: pointer; background: #fafafa; } diff --git a/electron-vue-template/src/renderer/components/amazon/TrademarkCheckPanel.vue b/electron-vue-template/src/renderer/components/amazon/TrademarkCheckPanel.vue index bff7e75..3cc1831 100644 --- a/electron-vue-template/src/renderer/components/amazon/TrademarkCheckPanel.vue +++ b/electron-vue-template/src/renderer/components/amazon/TrademarkCheckPanel.vue @@ -1,10 +1,11 @@ @@ -742,25 +927,28 @@ defineExpose({
1
-
导入Excel表格
+
+
导入Excel表格
+
在卖家精灵导出文档时,必须要勾选“导出主图”。导入的表格必须具备“品牌”,“商品主图”两个表头,商品主图必须为超链接。 - 点击查看示例
-
点击查看示例
+
📤
{{ uploadLoading ? '正在验证表头...' : '点击或将文件拖拽到这里上传' }}
支持 .xls .xlsx
- - + +
{{ trademarkFileName }} @@ -768,43 +956,47 @@ defineExpose({
- +
2
-
选择亚马逊商家账号
+
+
选择亚马逊商家账号
+
请确保账号地区与专利地区一致,不一致可能导致结果不准确或失败。
- +
- avatar + avatar {{ acc.name || acc.username }} ✔️
- +
添加账号 账号管理
- +
2
-
选择产品品牌地区
+
+
选择产品品牌地区
+
暂时仅支持美国品牌商标筛查,后续将开放更多地区,敬请期待。
@@ -813,14 +1005,19 @@ defineExpose({
- +
3
-
选择需查询的(可多选)
-
默认查询违规产品,可多选
- +
+
选择需查询的(可多选)
+
+
商标筛查包含以下维度,后续将开放更 + 多维度的筛查条件与自定义条件组合功 + 能,敬请期待 +
+
@@ -831,7 +1028,7 @@ defineExpose({
筛查未注册商标或TM标的商品
- +
@@ -841,7 +1038,7 @@ defineExpose({
筛查未注册商标的品牌
- +
@@ -855,60 +1052,123 @@ defineExpose({
- +
{{ completedSteps }}/{{ totalConfigSteps }} - + 开始筛查 - - 停止筛查 -
- - + + - Excel格式示例 + Excel格式示例