diff --git a/electron-vue-template/src/renderer/api/amazon.ts b/electron-vue-template/src/renderer/api/amazon.ts index 846562f..72dfba1 100644 --- a/electron-vue-template/src/renderer/api/amazon.ts +++ b/electron-vue-template/src/renderer/api/amazon.ts @@ -1,35 +1,17 @@ import { http } from './http'; export const amazonApi = { - // 上传Excel文件解析ASIN列表 importAsinFromExcel(file: File) { const formData = new FormData(); formData.append('file', file); return http.upload<{ code: number, data: { asinList: string[], total: number }, msg: string | null }>('/api/amazon/import/asin', formData); }, - getProductsBatch(asinList: string[], batchId: string, region: string) { - return http.post<{ code: number, data: { products: any[] }, msg: string | null }>('/api/amazon/products/batch', { asinList, batchId, region }); + getProductsBatch(asinList: string[], batchId: string, region: string, signal?: AbortSignal) { + return http.post<{ code: number, data: { products: any[] }, msg: string | null }>('/api/amazon/products/batch', { asinList, batchId, region }, signal); }, + getLatestProducts() { return http.get<{ code: number, data: { products: any[] }, msg: string | null }>('/api/amazon/products/latest'); - }, - getProductsByBatch(batchId: string) { - return http.get<{ products: any[] }>(`/api/amazon/products/batch/${batchId}`); - }, - updateProduct(productData: unknown) { - return http.post('/api/amazon/products/update', productData); - }, - deleteProduct(productId: string) { - return http.post('/api/amazon/products/delete', { id: productId }); - }, - getProductStats() { - return http.get('/api/amazon/stats'); - }, - searchProducts(searchParams: Record) { - return http.get('/api/amazon/products/search', searchParams); - }, - openGenmaiSpirit() { - return http.post('/api/system/genmai/open'); - }, + } }; diff --git a/electron-vue-template/src/renderer/api/http.ts b/electron-vue-template/src/renderer/api/http.ts index 8afab5c..4974d50 100644 --- a/electron-vue-template/src/renderer/api/http.ts +++ b/electron-vue-template/src/renderer/api/http.ts @@ -1,16 +1,13 @@ -// HTTP 工具:统一管理后端服务配置和请求 export type HttpMethod = 'GET' | 'POST' | 'DELETE'; -// 集中管理所有后端服务配置 export const CONFIG = { CLIENT_BASE: 'http://localhost:8081', - // RUOYI_BASE: 'http://192.168.1.89:8085', - RUOYI_BASE: 'http://8.138.23.49:8085', - SSE_URL: 'http://8.138.23.49:8085/monitor/account/events' + //RUOYI_BASE: 'http://8.138.23.49:8085', + RUOYI_BASE: 'http://192.168.1.89:8085', + SSE_URL: 'http://192.168.1.89:8085/monitor/account/events' } as const; function resolveBase(path: string): string { - // RuoYi 后端路径:鉴权、设备、反馈、版本、工具 if (path.startsWith('/monitor/') || path.startsWith('/system/') || path.startsWith('/tool/banma')) { return CONFIG.RUOYI_BASE; } @@ -26,16 +23,17 @@ function buildQuery(params?: Record): string { return query.toString() ? `?${query}` : ''; } -async function request(path: string, options: RequestInit): Promise { - // 获取token - let token = ''; +async function getToken(): Promise { try { const tokenModule = await import('../utils/token'); - token = tokenModule.getToken() || ''; - } catch (e) { - console.warn('获取token失败:', e); + return tokenModule.getToken() || ''; + } catch { + return ''; } +} +async function request(path: string, options: RequestInit & { signal?: AbortSignal }): Promise { + const token = await getToken(); const res = await fetch(`${resolveBase(path)}${path}`, { credentials: 'omit', cache: 'no-store', @@ -55,9 +53,6 @@ async function request(path: string, options: RequestInit): Promise { const contentType = res.headers.get('content-type') || ''; if (contentType.includes('application/json')) { const json: any = await res.json(); - // 业务状态码判断:支持两种格式 - // - erp_client_sb (本地服务): code=0 表示成功 - // - RuoYi 后端: code=200 表示成功 if (json.code !== undefined && json.code !== 0 && json.code !== 200) { throw new Error(json.msg || '请求失败'); } @@ -68,13 +63,14 @@ async function request(path: string, options: RequestInit): Promise { } export const http = { - get(path: string, params?: Record) { - return request(`${path}${buildQuery(params)}`, { method: 'GET' }); + get(path: string, params?: Record, signal?: AbortSignal) { + return request(`${path}${buildQuery(params)}`, { method: 'GET', signal }); }, - post(path: string, body?: unknown) { + post(path: string, body?: unknown, signal?: AbortSignal) { return request(path, { method: 'POST', - body: body ? JSON.stringify(body) : undefined + body: body ? JSON.stringify(body) : undefined, + signal }); }, @@ -82,42 +78,31 @@ export const http = { return request(path, { method: 'DELETE' }); }, - async upload(path: string, form: FormData) { - // 获取token - let token = ''; - try { - const tokenModule = await import('../utils/token'); - token = tokenModule.getToken() || ''; - } catch (e) { - console.warn('获取token失败:', e); - } - - const headers: Record = {}; - if (token) { - headers['Authorization'] = `Bearer ${token}`; - } - - return fetch(`${resolveBase(path)}${path}`, { + async upload(path: string, form: FormData, signal?: AbortSignal) { + const token = await getToken(); + const res = await fetch(`${resolveBase(path)}${path}`, { method: 'POST', body: form, credentials: 'omit', cache: 'no-store', - headers - }).then(async res => { - if (!res.ok) { - const text = await res.text().catch(() => ''); - throw new Error(text || `HTTP ${res.status}`); - } - const contentType = res.headers.get('content-type') || ''; - if (contentType.includes('application/json')) { - const json: any = await res.json(); - if (json.code !== undefined && json.code !== 0 && json.code !== 200) { - throw new Error(json.msg || '请求失败'); - } - return json as T; - } - return (await res.text()) as unknown as T; + headers: token ? { 'Authorization': `Bearer ${token}` } : {}, + signal }); + + if (!res.ok) { + const text = await res.text().catch(() => ''); + throw new Error(text || `HTTP ${res.status}`); + } + + const contentType = res.headers.get('content-type') || ''; + if (contentType.includes('application/json')) { + const json: any = await res.json(); + if (json.code !== undefined && json.code !== 0 && json.code !== 200) { + throw new Error(json.msg || '请求失败'); + } + return json as T; + } + return (await res.text()) as unknown as T; } }; diff --git a/electron-vue-template/src/renderer/api/system.ts b/electron-vue-template/src/renderer/api/system.ts new file mode 100644 index 0000000..f805908 --- /dev/null +++ b/electron-vue-template/src/renderer/api/system.ts @@ -0,0 +1,12 @@ +import { http } from './http'; + +export const systemApi = { + openGenmaiSpirit() { + return http.post('/api/system/genmai/open'); + }, + + clearCache() { + return http.post('/api/system/cache/clear'); + } +}; + diff --git a/electron-vue-template/src/renderer/api/zebra.ts b/electron-vue-template/src/renderer/api/zebra.ts index dedb771..c2cf3e8 100644 --- a/electron-vue-template/src/renderer/api/zebra.ts +++ b/electron-vue-template/src/renderer/api/zebra.ts @@ -18,23 +18,11 @@ export const zebraApi = { return http.get('/api/banma/shops', params as Record) }, - getOrders(params: any) { - return http.get('/api/banma/orders', params as Record) - }, - - getOrdersByBatch(batchId: string) { - return http.get(`/api/banma/orders/batch/${batchId}`) + getOrders(params: any, signal?: AbortSignal) { + return http.get('/api/banma/orders', params as Record, signal) }, getLatestOrders() { return http.get('/api/banma/orders/latest') - }, - - getOrderStats() { - return http.get('/api/banma/orders/stats') - }, - - searchOrders(searchParams: Record) { - return http.get('/api/banma/orders/search', searchParams) } } \ No newline at end of file diff --git a/electron-vue-template/src/renderer/components/amazon/AmazonDashboard.vue b/electron-vue-template/src/renderer/components/amazon/AmazonDashboard.vue index e0aee0d..7f61e9c 100644 --- a/electron-vue-template/src/renderer/components/amazon/AmazonDashboard.vue +++ b/electron-vue-template/src/renderer/components/amazon/AmazonDashboard.vue @@ -2,6 +2,7 @@ import { ref, computed, onMounted, defineAsyncComponent, inject } from 'vue' import { ElMessage, ElMessageBox } from 'element-plus' import { amazonApi } from '../../api/amazon' +import { systemApi } from '../../api/system' import { handlePlatformFileExport } from '../../utils/settings' const TrialExpiredDialog = defineAsyncComponent(() => import('../common/TrialExpiredDialog.vue')) @@ -21,6 +22,7 @@ const progressVisible = ref(false) // 进度条是否显示(完成后仍保留 const localProductData = ref([]) // 本地产品数据 const currentAsin = ref('') // 当前处理的ASIN const genmaiLoading = ref(false) // Genmai Spirit加载状态 +let abortController: AbortController | null = null // 请求取消控制器 // 分页配置 const currentPage = ref(1) @@ -130,7 +132,7 @@ async function batchGetProductInfo(asinList: string[]) { currentAsin.value = `正在处理第${i + 1}/${totalBatches}批 (${batchAsins.join(', ')})` try { - const result = await amazonApi.getProductsBatch(batchAsins, batchId, region.value) + const result = await amazonApi.getProductsBatch(batchAsins, batchId, region.value, abortController?.signal) if (result?.data?.products?.length > 0) { localProductData.value.push(...result.data.products) @@ -142,7 +144,8 @@ async function batchGetProductInfo(asinList: string[]) { const actualCount = result?.data?.products?.length || 0 failedCount += Math.max(0, expectedCount - actualCount) - } catch (error) { + } catch (error: any) { + if (error.name === 'AbortError') break failedCount += batchAsins.length console.error(`批次${i + 1}失败:`, error) } @@ -164,8 +167,10 @@ async function batchGetProductInfo(asinList: string[]) { } catch (error: any) { - showMessage(error.message || '批量获取产品信息失败', 'error') - currentAsin.value = '处理失败' + if (error.name !== 'AbortError') { + showMessage(error.message || '批量获取产品信息失败', 'error') + currentAsin.value = '处理失败' + } } finally { tableLoading.value = false } @@ -177,6 +182,7 @@ async function startQueuedFetch() { showMessage('请先导入ASIN列表', 'warning') return } + abortController = new AbortController() loading.value = true progressVisible.value = true tableLoading.value = true @@ -185,6 +191,7 @@ async function startQueuedFetch() { } finally { tableLoading.value = false loading.value = false + abortController = null } } @@ -240,12 +247,13 @@ function isOutOfStock(product: any) { // 停止获取操作 function stopFetch() { + abortController?.abort() + abortController = null loading.value = false currentAsin.value = '已停止' showMessage('已停止获取产品数据', 'info') } -// 打开Genmai Spirit工具 async function openGenmaiSpirit() { try { await ElMessageBox.confirm('打开跟卖精灵会关闭所有谷歌浏览器进程,是否继续?', '提示', { @@ -255,7 +263,7 @@ async function openGenmaiSpirit() { }) genmaiLoading.value = true try { - await amazonApi.openGenmaiSpirit() + await systemApi.openGenmaiSpirit() } catch (error: any) { showMessage(error.message || '打开跟卖精灵失败', 'error') } finally { diff --git a/electron-vue-template/src/renderer/components/zebra/ZebraDashboard.vue b/electron-vue-template/src/renderer/components/zebra/ZebraDashboard.vue index 116ed41..9f98441 100644 --- a/electron-vue-template/src/renderer/components/zebra/ZebraDashboard.vue +++ b/electron-vue-template/src/renderer/components/zebra/ZebraDashboard.vue @@ -40,6 +40,7 @@ const fetchCurrentPage = ref(1) const fetchTotalPages = ref(0) const fetchTotalItems = ref(0) const isFetching = ref(false) +let abortController: AbortController | null = null // 试用期过期弹框 const showTrialExpiredDialog = ref(false) @@ -113,6 +114,7 @@ async function fetchData() { return } + abortController = new AbortController() loading.value = true isFetching.value = true showProgress.value = true @@ -130,7 +132,7 @@ async function fetchPageData(startDate: string, endDate: string) { if (!isFetching.value) return try { - const data = await zebraApi.getOrders({ + const response = await zebraApi.getOrders({ accountId: Number(accountId.value) || undefined, startDate, endDate, @@ -138,8 +140,9 @@ async function fetchPageData(startDate: string, endDate: string) { pageSize: 50, shopIds: selectedShops.value.join(','), batchId: currentBatchId.value - }) + }, abortController?.signal) + const data = (response as any)?.data || response const orders = data.orders || [] allOrderData.value = [...allOrderData.value, ...orders] @@ -154,8 +157,10 @@ async function fetchPageData(startDate: string, endDate: string) { progressPercentage.value = 100 finishFetching() } - } catch (e) { - console.error('获取订单数据失败:', e) + } catch (e: any) { + if (e.name !== 'AbortError') { + console.error('获取订单数据失败:', e) + } finishFetching() } } @@ -163,6 +168,7 @@ async function fetchPageData(startDate: string, endDate: string) { function finishFetching() { isFetching.value = false loading.value = false + abortController = null // 确保进度条完全填满 progressPercentage.value = 100 currentPage.value = 1 @@ -170,6 +176,8 @@ function finishFetching() { } function stopFetch() { + abortController?.abort() + abortController = null isFetching.value = false loading.value = false // 进度条保留显示,不自动隐藏 diff --git a/erp_client_sb/src/main/java/com/tashow/erp/controller/AmazonController.java b/erp_client_sb/src/main/java/com/tashow/erp/controller/AmazonController.java index c869fce..1d4e9a9 100644 --- a/erp_client_sb/src/main/java/com/tashow/erp/controller/AmazonController.java +++ b/erp_client_sb/src/main/java/com/tashow/erp/controller/AmazonController.java @@ -1,63 +1,42 @@ package com.tashow.erp.controller; import com.tashow.erp.entity.AmazonProductEntity; import com.tashow.erp.repository.AmazonProductRepository; -import com.tashow.erp.service.IAmazonScrapingService; +import com.tashow.erp.service.AmazonScrapingService; import com.tashow.erp.utils.ExcelParseUtil; -import com.tashow.erp.utils.ExcelExportUtil; import com.tashow.erp.utils.JsonData; import com.tashow.erp.utils.LoggerUtil; -import com.tashow.erp.fx.controller.JavaBridge; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; -import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.ArrayList; -import java.util.Optional; + @RestController @RequestMapping("/api/amazon") public class AmazonController { private static final Logger logger = LoggerUtil.getLogger(AmazonController.class); @Autowired - private IAmazonScrapingService amazonScrapingService; + private AmazonScrapingService amazonScrapingService; @Autowired private AmazonProductRepository amazonProductRepository; - /** - * 批量获取亚马逊产品信息 - */ @PostMapping("/products/batch") - public JsonData batchGetProducts(@RequestBody Object request) { + public JsonData batchGetProducts(@RequestBody Map request) { @SuppressWarnings("unchecked") - Map requestMap = (Map) request; - List asinList = (List) requestMap.get("asinList"); - String batchId = (String) requestMap.get("batchId"); - String region = (String) requestMap.getOrDefault("region", "JP"); + List asinList = (List) request.get("asinList"); + String batchId = (String) request.get("batchId"); + String region = (String) request.getOrDefault("region", "JP"); List products = amazonScrapingService.batchGetProductInfo(asinList, batchId, region); - Map result = new HashMap<>(); - result.put("products", products); - result.put("total", products.size()); - return JsonData.buildSuccess(result); + return JsonData.buildSuccess(Map.of("products", products, "total", products.size())); } - /** - * 获取最新产品数据 - */ @GetMapping("/products/latest") public JsonData getLatestProducts() { List products = amazonProductRepository.findLatestProducts(); - Map result = new HashMap<>(); - result.put("products", products); - result.put("total", products.size()); - return JsonData.buildSuccess(result); + return JsonData.buildSuccess(Map.of("products", products, "total", products.size())); } - /** - * 解析Excel文件获取ASIN列表 - */ @PostMapping("/import/asin") public JsonData importAsinFromExcel(@RequestParam("file") MultipartFile file) { try { @@ -65,16 +44,10 @@ public class AmazonController { if (asinList.isEmpty()) { return JsonData.buildError("未从文件中解析到ASIN数据"); } - - Map result = new HashMap<>(); - result.put("asinList", asinList); - result.put("total", asinList.size()); - return JsonData.buildSuccess(result); - + return JsonData.buildSuccess(Map.of("asinList", asinList, "total", asinList.size())); } catch (Exception e) { logger.error("解析文件失败: {}", e.getMessage(), e); return JsonData.buildError("解析失败: " + e.getMessage()); } } - } \ No newline at end of file diff --git a/erp_client_sb/src/main/java/com/tashow/erp/controller/BanmaOrderController.java b/erp_client_sb/src/main/java/com/tashow/erp/controller/BanmaOrderController.java index 5ff3dd3..c52b9be 100644 --- a/erp_client_sb/src/main/java/com/tashow/erp/controller/BanmaOrderController.java +++ b/erp_client_sb/src/main/java/com/tashow/erp/controller/BanmaOrderController.java @@ -1,57 +1,45 @@ package com.tashow.erp.controller; -import com.tashow.erp.fx.controller.JavaBridge; import com.tashow.erp.repository.BanmaOrderRepository; -import com.tashow.erp.service.IBanmaOrderService; -import com.tashow.erp.utils.ExcelExportUtil; +import com.tashow.erp.service.BanmaOrderService; import com.tashow.erp.utils.JsonData; import com.tashow.erp.utils.LoggerUtil; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import org.springframework.web.client.RestTemplate; import java.util.HashMap; import java.util.List; import java.util.Map; + @RestController @RequestMapping("/api/banma") public class BanmaOrderController { private static final Logger logger = LoggerUtil.getLogger(BanmaOrderController.class); @Autowired - IBanmaOrderService banmaOrderService; + BanmaOrderService banmaOrderService; @Autowired BanmaOrderRepository banmaOrderRepository; @GetMapping("/orders") - public ResponseEntity> getOrders( + public JsonData getOrders( @RequestParam(required = false, name = "accountId") Long accountId, @RequestParam(required = false, name = "startDate") String startDate, @RequestParam(required = false, name = "endDate") String endDate, @RequestParam(defaultValue = "1", name = "page") int page, @RequestParam(defaultValue = "10", name = "pageSize") int pageSize, - @RequestParam( "batchId") String batchId, + @RequestParam("batchId") String batchId, @RequestParam(required = false, name = "shopIds") String shopIds) { List shopIdList = shopIds != null ? java.util.Arrays.asList(shopIds.split(",")) : null; Map result = banmaOrderService.getOrdersByPage(accountId, startDate, endDate, page, pageSize, batchId, shopIdList); - return ResponseEntity.ok(result); + return result.containsKey("success") && !(Boolean)result.get("success") + ? JsonData.buildError((String)result.get("message")) + : JsonData.buildSuccess(result); } - /** - * 获取店铺列表 - */ @GetMapping("/shops") public JsonData getShops(@RequestParam(required = false, name = "accountId") Long accountId) { - try { - Map response = banmaOrderService.getShops(accountId); - return JsonData.buildSuccess(response); - } catch (Exception e) { - logger.error("获取店铺列表失败: {}", e.getMessage(), e); - return JsonData.buildError("获取店铺列表失败: " + e.getMessage()); - } + Map response = banmaOrderService.getShops(accountId); + return JsonData.buildSuccess(response); } - /** - * 获取最新订单数据 - */ @GetMapping("/orders/latest") public JsonData getLatestOrders() { com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper(); @@ -68,8 +56,6 @@ public class BanmaOrderController { }) .filter(order -> !order.isEmpty()) .toList(); - return JsonData.buildSuccess(Map.of("orders", orders, "total", orders.size())); } - } \ No newline at end of file diff --git a/erp_client_sb/src/main/java/com/tashow/erp/controller/RakutenController.java b/erp_client_sb/src/main/java/com/tashow/erp/controller/RakutenController.java index 94b49af..0d6cee8 100644 --- a/erp_client_sb/src/main/java/com/tashow/erp/controller/RakutenController.java +++ b/erp_client_sb/src/main/java/com/tashow/erp/controller/RakutenController.java @@ -2,31 +2,19 @@ package com.tashow.erp.controller; import com.tashow.erp.model.RakutenProduct; import com.tashow.erp.model.SearchResult; -import com.tashow.erp.repository.RakutenProductRepository; import com.tashow.erp.service.Alibaba1688Service; -import com.tashow.erp.service.IRakutenCacheService; +import com.tashow.erp.service.RakutenCacheService; import com.tashow.erp.service.RakutenScrapingService; -import com.tashow.erp.service.impl.Alibaba1688ServiceImpl; import com.tashow.erp.utils.DataReportUtil; import com.tashow.erp.utils.ExcelParseUtil; import com.tashow.erp.utils.JsonData; -import com.tashow.erp.utils.QiniuUtil; -import com.tashow.erp.fx.controller.JavaBridge; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; -import org.springframework.web.client.RestTemplate; - -import java.time.Instant; -import java.time.LocalDateTime; -import java.time.ZoneOffset; import java.util.*; import java.util.stream.Collectors; -import java.util.Base64; -import java.util.regex.Matcher; -import java.util.regex.Pattern; @RestController @RequestMapping("/api/rakuten") @@ -37,19 +25,10 @@ public class RakutenController { @Autowired private Alibaba1688Service alibaba1688Service; @Autowired - private IRakutenCacheService rakutenCacheService; - @Autowired - private JavaBridge javaBridge; + private RakutenCacheService rakutenCacheService; @Autowired private DataReportUtil dataReportUtil; - /** - * 获取乐天商品数据 - * - * @param file Excel文件(首列为店铺名) - * @param batchId 可选,批次号 - * @return JsonData 响应 - */ @PostMapping(value = "/products") public JsonData getProducts(@RequestParam("file") MultipartFile file, @RequestParam(value = "batchId", required = false) String batchId) { try { @@ -80,21 +59,23 @@ public class RakutenController { if (!newProducts.isEmpty()) { rakutenCacheService.saveProductsWithSessionId(newProducts, batchId); } - // 4. 上报缓存数据使用情况 int cachedCount = allProducts.size() - newProducts.size(); if (cachedCount > 0) { dataReportUtil.reportDataCollection("RAKUTEN_CACHE", cachedCount, "0"); } - return JsonData.buildSuccess(Map.of("products", allProducts, "total", allProducts.size(), "sessionId", batchId, "skippedShops", skippedShops, "newProductsCount", newProducts.size())); + return JsonData.buildSuccess(Map.of( + "products", allProducts, + "total", allProducts.size(), + "sessionId", batchId, + "skippedShops", skippedShops, + "newProductsCount", newProducts.size() + )); } catch (Exception e) { log.error("获取乐天商品失败", e); return JsonData.buildError("获取乐天商品失败: " + e.getMessage()); } } - /** - * 1688识图搜索API - 自动保存1688搜索结果 - */ @PostMapping("/search1688") public JsonData search1688(@RequestBody Map params) { String imageUrl = (String) params.get("imageUrl"); @@ -109,21 +90,14 @@ public class RakutenController { } } - @GetMapping("/products/latest") public JsonData getLatestProducts() { try { List> products = rakutenScrapingService.getLatestProductsForDisplay(); return JsonData.buildSuccess(Map.of("products", products, "total", products.size())); } catch (Exception e) { - - e.printStackTrace(); - log.info("获取最新商品数据失败", e); + log.error("获取最新商品数据失败", e); return JsonData.buildError("获取最新数据失败: " + e.getMessage()); } } - - - - } \ No newline at end of file diff --git a/erp_client_sb/src/main/java/com/tashow/erp/controller/SystemController.java b/erp_client_sb/src/main/java/com/tashow/erp/controller/SystemController.java index d8cf43e..96d78b1 100644 --- a/erp_client_sb/src/main/java/com/tashow/erp/controller/SystemController.java +++ b/erp_client_sb/src/main/java/com/tashow/erp/controller/SystemController.java @@ -2,49 +2,36 @@ package com.tashow.erp.controller; import com.tashow.erp.entity.AuthTokenEntity; import com.tashow.erp.repository.AuthTokenRepository; -import com.tashow.erp.service.impl.CacheManagementServiceImpl; +import com.tashow.erp.service.CacheService; import com.tashow.erp.service.impl.GenmaiServiceImpl; import com.tashow.erp.utils.JsonData; +import com.tashow.erp.utils.LoggerUtil; +import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.*; import org.springframework.web.bind.annotation.*; import org.springframework.web.client.RestTemplate; - -import java.util.HashMap; import java.util.Map; -/** - * 系统级接口控制器 - * 整合:认证、配置、版本、工具、代理等功能 - */ @RestController @RequestMapping("/api/system") public class SystemController { - + private static final Logger logger = LoggerUtil.getLogger(SystemController.class); @Autowired private AuthTokenRepository authTokenRepository; - @Autowired private GenmaiServiceImpl genmaiService; - @Autowired - private CacheManagementServiceImpl cacheManagementService; - + private CacheService cacheService; @Autowired private RestTemplate restTemplate; - @Value("${project.version:2.3.6}") private String currentVersion; - @Value("${project.build.time:}") private String buildTime; - @Value("${api.server.base-url}") private String serverBaseUrl; - /** - * 保存认证密钥 - */ @PostMapping("/auth/save") public JsonData saveAuth(@RequestBody Map data) { String serviceName = (String) data.get("serviceName"); @@ -52,17 +39,13 @@ public class SystemController { if (serviceName == null || authKey == null) { return JsonData.buildError("serviceName和authKey不能为空"); } - AuthTokenEntity entity = authTokenRepository.findByServiceName(serviceName) - .orElse(new AuthTokenEntity()); + AuthTokenEntity entity = authTokenRepository.findByServiceName(serviceName).orElse(new AuthTokenEntity()); entity.setServiceName(serviceName); entity.setToken(authKey); authTokenRepository.save(entity); return JsonData.buildSuccess("认证信息保存成功"); } - /** - * 获取认证密钥 - */ @GetMapping("/auth/get") public JsonData getAuth(@RequestParam String serviceName) { return JsonData.buildSuccess(authTokenRepository.findByServiceName(serviceName) @@ -70,82 +53,41 @@ public class SystemController { .orElse(null)); } - /** - * 删除认证密钥 - */ @DeleteMapping("/auth/remove") public JsonData removeAuth(@RequestParam String serviceName) { - authTokenRepository.findByServiceName(serviceName) - .ifPresent(authTokenRepository::delete); + authTokenRepository.findByServiceName(serviceName).ifPresent(authTokenRepository::delete); return JsonData.buildSuccess("认证信息删除成功"); } - // ==================== 设备管理 ==================== - - /** - * 获取设备ID - */ @GetMapping("/device-id") public JsonData getDeviceId() { - String deviceId = com.tashow.erp.utils.DeviceUtils.generateDeviceId(); - return JsonData.buildSuccess(deviceId); + return JsonData.buildSuccess(com.tashow.erp.utils.DeviceUtils.generateDeviceId()); } - /** - * 获取本机内网IP地址 - */ @GetMapping("/local-ip") public JsonData getLocalIp() { try { - java.net.InetAddress localHost = java.net.InetAddress.getLocalHost(); - return JsonData.buildSuccess(localHost.getHostAddress()); + return JsonData.buildSuccess(java.net.InetAddress.getLocalHost().getHostAddress()); } catch (Exception e) { return JsonData.buildSuccess("127.0.0.1"); } } - // ==================== 版本信息 ==================== - - /** - * 获取当前版本号 - */ @GetMapping("/version") public Map getVersion() { - Map result = new HashMap<>(); - result.put("success", true); - result.put("currentVersion", currentVersion); - result.put("buildTime", buildTime); - return result; + return Map.of("success", true, "currentVersion", currentVersion, "buildTime", buildTime); } - // ==================== 配置信息 ==================== - - /** - * 获取服务器配置 - */ @GetMapping("/config/server") public Map getServerConfig() { - return Map.of( - "baseUrl", serverBaseUrl, - "sseUrl", serverBaseUrl + "/monitor/account/events" - ); + return Map.of("baseUrl", serverBaseUrl, "sseUrl", serverBaseUrl + "/monitor/account/events"); } - // ==================== 工具功能 ==================== - - /** - * 打开跟卖精灵网页 - */ @PostMapping("/genmai/open") public void openGenmaiWebsite() { genmaiService.openGenmaiWebsite(); } - // ==================== 图片代理 ==================== - - /** - * 代理获取图片(解决CORS跨域问题) - */ @GetMapping("/proxy/image") public ResponseEntity proxyImage(@RequestParam("url") String imageUrl) { if (imageUrl == null || imageUrl.isEmpty()) { @@ -178,24 +120,15 @@ public class SystemController { return new ResponseEntity<>(response.getBody(), responseHeaders, HttpStatus.OK); } catch (Exception e) { - e.printStackTrace(); + logger.error("代理图片失败: {}", imageUrl, e); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); } } - // ==================== 缓存管理 ==================== - - /** - * 清理缓存 - */ @PostMapping("/cache/clear") public JsonData clearCache() { - try { - cacheManagementService.clearCache(); - return JsonData.buildSuccess("缓存清理成功"); - } catch (Exception e) { - return JsonData.buildError("清理缓存失败: " + e.getMessage()); - } + cacheService.clearCache(); + return JsonData.buildSuccess("缓存清理成功"); } } diff --git a/erp_client_sb/src/main/java/com/tashow/erp/security/LocalJwtAuthInterceptor.java b/erp_client_sb/src/main/java/com/tashow/erp/security/LocalJwtAuthInterceptor.java index 6922db6..0f54156 100644 --- a/erp_client_sb/src/main/java/com/tashow/erp/security/LocalJwtAuthInterceptor.java +++ b/erp_client_sb/src/main/java/com/tashow/erp/security/LocalJwtAuthInterceptor.java @@ -1,7 +1,7 @@ package com.tashow.erp.security; import com.fasterxml.jackson.databind.ObjectMapper; -import com.tashow.erp.service.IAuthService; +import com.tashow.erp.service.impl.AuthServiceImpl; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.stereotype.Component; @@ -10,16 +10,13 @@ import org.springframework.web.servlet.HandlerInterceptor; import java.io.IOException; import java.util.Base64; - /** - * 本地拦截器 - */ @Component public class LocalJwtAuthInterceptor implements HandlerInterceptor { - private final IAuthService authService; + private final AuthServiceImpl authService; private final ObjectMapper objectMapper = new ObjectMapper(); - public LocalJwtAuthInterceptor(IAuthService authService) { + public LocalJwtAuthInterceptor(AuthServiceImpl authService) { this.authService = authService; } diff --git a/erp_client_sb/src/main/java/com/tashow/erp/service/IAmazonScrapingService.java b/erp_client_sb/src/main/java/com/tashow/erp/service/AmazonScrapingService.java similarity index 77% rename from erp_client_sb/src/main/java/com/tashow/erp/service/IAmazonScrapingService.java rename to erp_client_sb/src/main/java/com/tashow/erp/service/AmazonScrapingService.java index 278bde2..df27412 100644 --- a/erp_client_sb/src/main/java/com/tashow/erp/service/IAmazonScrapingService.java +++ b/erp_client_sb/src/main/java/com/tashow/erp/service/AmazonScrapingService.java @@ -3,12 +3,7 @@ package com.tashow.erp.service; import com.tashow.erp.entity.AmazonProductEntity; import java.util.List; -/** - * 亚马逊数据采集服务接口 - * - * @author ruoyi - */ -public interface IAmazonScrapingService { +public interface AmazonScrapingService { /** * 批量获取亚马逊产品信息 @@ -19,10 +14,5 @@ public interface IAmazonScrapingService { * @return 产品信息列表 */ List batchGetProductInfo(List asinList, String batchId, String region); - +} - - - - -} \ No newline at end of file diff --git a/erp_client_sb/src/main/java/com/tashow/erp/service/IBanmaOrderService.java b/erp_client_sb/src/main/java/com/tashow/erp/service/BanmaOrderService.java similarity index 88% rename from erp_client_sb/src/main/java/com/tashow/erp/service/IBanmaOrderService.java rename to erp_client_sb/src/main/java/com/tashow/erp/service/BanmaOrderService.java index b6487a6..ffbd99e 100644 --- a/erp_client_sb/src/main/java/com/tashow/erp/service/IBanmaOrderService.java +++ b/erp_client_sb/src/main/java/com/tashow/erp/service/BanmaOrderService.java @@ -3,12 +3,7 @@ package com.tashow.erp.service; import java.util.List; import java.util.Map; -/** - * 斑马订单服务接口 - * - * @author ruoyi - */ -public interface IBanmaOrderService { +public interface BanmaOrderService { // 客户端不再暴露刷新认证Token @@ -30,3 +25,4 @@ public interface IBanmaOrderService { */ Map getOrdersByPage(Long accountId, String startDate, String endDate, int page, int pageSize, String batchId, List shopIds); } + diff --git a/erp_client_sb/src/main/java/com/tashow/erp/service/impl/CacheManagementServiceImpl.java b/erp_client_sb/src/main/java/com/tashow/erp/service/CacheService.java similarity index 52% rename from erp_client_sb/src/main/java/com/tashow/erp/service/impl/CacheManagementServiceImpl.java rename to erp_client_sb/src/main/java/com/tashow/erp/service/CacheService.java index e18c296..13f2655 100644 --- a/erp_client_sb/src/main/java/com/tashow/erp/service/impl/CacheManagementServiceImpl.java +++ b/erp_client_sb/src/main/java/com/tashow/erp/service/CacheService.java @@ -1,39 +1,49 @@ -package com.tashow.erp.service.impl; +package com.tashow.erp.service; +import com.tashow.erp.entity.AuthTokenEntity; import com.tashow.erp.repository.*; -import com.tashow.erp.service.ICacheManagementService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDateTime; +import java.util.Optional; -/** - * 缓存管理服务实现 - */ @Service -public class CacheManagementServiceImpl implements ICacheManagementService { - +public class CacheService { + private static final Logger logger = LoggerFactory.getLogger(CacheService.class); + + @Autowired + private AuthTokenRepository authTokenRepository; @Autowired private RakutenProductRepository rakutenProductRepository; - @Autowired private AmazonProductRepository amazonProductRepository; - @Autowired private Alibaba1688ProductRepository alibaba1688ProductRepository; - @Autowired private ZebraOrderRepository zebraOrderRepository; - @Autowired private BanmaOrderRepository banmaOrderRepository; - @Autowired private CacheDataRepository cacheDataRepository; - @Autowired private UpdateStatusRepository updateStatusRepository; - @Override + public void saveAuthToken(String service, String token, long expireTimeMillis) { + try { + Optional existing = authTokenRepository.findByServiceName(service); + AuthTokenEntity entity = existing.orElse(new AuthTokenEntity()); + entity.setServiceName(service); + entity.setToken(token); + entity.setExpireTime(LocalDateTime.now().plusSeconds(expireTimeMillis / 1000)); + authTokenRepository.save(entity); + } catch (Exception e) { + logger.error("保存认证令牌失败: {}", service, e); + } + } + @Transactional public void clearCache() { rakutenProductRepository.deleteAll(); diff --git a/erp_client_sb/src/main/java/com/tashow/erp/service/IAuthService.java b/erp_client_sb/src/main/java/com/tashow/erp/service/IAuthService.java deleted file mode 100644 index 834f5f9..0000000 --- a/erp_client_sb/src/main/java/com/tashow/erp/service/IAuthService.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.tashow.erp.service; - -import java.util.Map; - -/** - * 认证服务接口 - */ -public interface IAuthService { - - /** - * 客户端登录认证 - */ - Map login(String username, String password); - - /** - * 获取客户端信息 - */ - Map getClientInfo(); - - /** - * 上报错误 - */ - void reportError(String errorType, String errorMessage, Exception e); - - /** - * 检查版本更新 - */ - String checkVersion(String currentVersion); - - /** - * 获取客户端ID - */ - String getClientId(); - - void logout(); - - /** - * 验证token - */ - Map verifyToken(String token); - - - /** - * 注册新账号 - */ - Map register(String username, String password); - - /** - * 检查用户名是否可用 - */ - boolean checkUsername(String username); -} \ No newline at end of file diff --git a/erp_client_sb/src/main/java/com/tashow/erp/service/ICacheService.java b/erp_client_sb/src/main/java/com/tashow/erp/service/ICacheService.java deleted file mode 100644 index c25ac7a..0000000 --- a/erp_client_sb/src/main/java/com/tashow/erp/service/ICacheService.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.tashow.erp.service; - -/** - * 缓存服务接口 - */ -public interface ICacheService { - - /** - * 保存认证令牌 - */ - void saveAuthToken(String service, String token, long expireTimeMillis); -} \ No newline at end of file diff --git a/erp_client_sb/src/main/java/com/tashow/erp/service/IGenmaiService.java b/erp_client_sb/src/main/java/com/tashow/erp/service/IGenmaiService.java deleted file mode 100644 index eb2ef84..0000000 --- a/erp_client_sb/src/main/java/com/tashow/erp/service/IGenmaiService.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.tashow.erp.service; - -/** - * 跟卖精灵服务接口 - * - * @author ruoyi - */ -public interface IGenmaiService { - - /** - * 使用Playwright打开跟卖精灵网页 - * - * @return 是否成功打开 - */ - void openGenmaiWebsite(); - - -} \ No newline at end of file diff --git a/erp_client_sb/src/main/java/com/tashow/erp/service/IRakutenCacheService.java b/erp_client_sb/src/main/java/com/tashow/erp/service/RakutenCacheService.java similarity index 92% rename from erp_client_sb/src/main/java/com/tashow/erp/service/IRakutenCacheService.java rename to erp_client_sb/src/main/java/com/tashow/erp/service/RakutenCacheService.java index c80acdb..5cf361a 100644 --- a/erp_client_sb/src/main/java/com/tashow/erp/service/IRakutenCacheService.java +++ b/erp_client_sb/src/main/java/com/tashow/erp/service/RakutenCacheService.java @@ -1,13 +1,9 @@ package com.tashow.erp.service; import com.tashow.erp.model.RakutenProduct; - import java.util.List; -/** - * 乐天产品缓存服务接口 - */ -public interface IRakutenCacheService { +public interface RakutenCacheService { /** * 保存产品数据 @@ -19,8 +15,6 @@ public interface IRakutenCacheService { */ void saveProductsWithSessionId(List products, String sessionId); - - /** * 检查店铺是否有最近的数据(12小时内) */ @@ -45,6 +39,5 @@ public interface IRakutenCacheService { * 清理指定店铺12小时内的重复数据,为新采集做准备 */ void cleanRecentDuplicateData(String shopName); +} - -} \ No newline at end of file diff --git a/erp_client_sb/src/main/java/com/tashow/erp/service/impl/AmazonScrapingServiceImpl.java b/erp_client_sb/src/main/java/com/tashow/erp/service/impl/AmazonScrapingServiceImpl.java index 5b48f74..6e5276b 100644 --- a/erp_client_sb/src/main/java/com/tashow/erp/service/impl/AmazonScrapingServiceImpl.java +++ b/erp_client_sb/src/main/java/com/tashow/erp/service/impl/AmazonScrapingServiceImpl.java @@ -1,6 +1,7 @@ package com.tashow.erp.service.impl; import com.tashow.erp.entity.AmazonProductEntity; import com.tashow.erp.repository.AmazonProductRepository; +import com.tashow.erp.service.AmazonScrapingService; import com.tashow.erp.utils.DataReportUtil; import com.tashow.erp.utils.ErrorReporter; import com.tashow.erp.utils.RakutenProxyUtil; @@ -20,7 +21,7 @@ import java.util.concurrent.ConcurrentHashMap; * @author ruoyi */ @Service -public class AmazonScrapingServiceImpl implements IAmazonScrapingService, PageProcessor { +public class AmazonScrapingServiceImpl implements AmazonScrapingService, PageProcessor { @Autowired private AmazonProductRepository amazonProductRepository; @Autowired @@ -68,8 +69,9 @@ public class AmazonScrapingServiceImpl implements IAmazonScrapingService, PagePr if (isEmpty(price)) errorReporter.reportDataEmpty("amazon", asin, price); if (isEmpty(seller)) errorReporter.reportDataEmpty("amazon", asin, seller); + AmazonProductEntity entity = new AmazonProductEntity(); - entity.setAsin(asin != null ? asin : ""); + entity.setAsin(asin == null ? "" : asin); entity.setPrice(price); entity.setSeller(seller); resultCache.put(asin, entity); diff --git a/erp_client_sb/src/main/java/com/tashow/erp/service/impl/AuthServiceImpl.java b/erp_client_sb/src/main/java/com/tashow/erp/service/impl/AuthServiceImpl.java index 30424b7..ac6f6f3 100644 --- a/erp_client_sb/src/main/java/com/tashow/erp/service/impl/AuthServiceImpl.java +++ b/erp_client_sb/src/main/java/com/tashow/erp/service/impl/AuthServiceImpl.java @@ -1,24 +1,17 @@ package com.tashow.erp.service.impl; -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import com.tashow.erp.service.IAuthService; import com.tashow.erp.utils.ApiForwarder; import com.tashow.erp.utils.DeviceUtils; import lombok.Getter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; - import java.util.HashMap; import java.util.Map; -/** - * 认证服务实现类 - 简化版 - * 仅提供错误上报和客户端信息获取功能 - */ @Service -public class AuthServiceImpl implements IAuthService { +public class AuthServiceImpl { @Value("${project.version:2.1.0}") private String appVersion; @@ -29,10 +22,6 @@ public class AuthServiceImpl implements IAuthService { @Getter private String clientId = DeviceUtils.generateDeviceId(); - /** - * 获取客户端基本信息 - */ - @Override public Map getClientInfo() { Map info = new HashMap<>(); info.put("clientId", clientId); @@ -41,10 +30,6 @@ public class AuthServiceImpl implements IAuthService { return info; } - /** - * 上报错误信息 - */ - @Override public void reportError(String errorType, String errorMessage, Exception e) { try { Map errorData = new HashMap<>(); diff --git a/erp_client_sb/src/main/java/com/tashow/erp/service/impl/BanmaOrderServiceImpl.java b/erp_client_sb/src/main/java/com/tashow/erp/service/impl/BanmaOrderServiceImpl.java index 58c552a..dbc9795 100644 --- a/erp_client_sb/src/main/java/com/tashow/erp/service/impl/BanmaOrderServiceImpl.java +++ b/erp_client_sb/src/main/java/com/tashow/erp/service/impl/BanmaOrderServiceImpl.java @@ -2,6 +2,8 @@ package com.tashow.erp.service.impl; import com.fasterxml.jackson.databind.ObjectMapper; import com.tashow.erp.entity.BanmaOrderEntity; import com.tashow.erp.repository.BanmaOrderRepository; +import com.tashow.erp.service.BanmaOrderService; +import com.tashow.erp.service.CacheService; import com.tashow.erp.utils.DataReportUtil; import com.tashow.erp.utils.ErrorReporter; import com.tashow.erp.utils.LoggerUtil; @@ -24,7 +26,7 @@ import java.util.stream.Collectors; * @author ruoyi */ @Service -public class BanmaOrderServiceImpl { +public class BanmaOrderServiceImpl implements BanmaOrderService { private static final Logger logger = LoggerUtil.getLogger(BanmaOrderServiceImpl.class); private static final String API_URL = "https://banma365.cn/api/order/list?%srecipientName=&page=%d&size=%d&markFlag=0&state=4&_t=%d"; private static final String API_URL_WITH_TIME = "https://banma365.cn/api/order/list?%srecipientName=&page=%d&size=%d&markFlag=0&state=4&orderedAtStart=%s&orderedAtEnd=%s&_t=%d"; @@ -34,7 +36,7 @@ public class BanmaOrderServiceImpl { private String ruoyiAdminBase; private RestTemplate restTemplate; private final ObjectMapper objectMapper = new ObjectMapper(); - private final CacheServiceImpl cacheService; + private final CacheService cacheService; private final BanmaOrderRepository banmaOrderRepository; private final DataReportUtil dataReportUtil; private final ErrorReporter errorReporter; @@ -44,7 +46,7 @@ public class BanmaOrderServiceImpl { private String currentBatchSessionId = null; // 物流信息缓存,避免重复查询 private final Map trackingInfoCache = new ConcurrentHashMap<>(); - public BanmaOrderServiceImpl(BanmaOrderRepository banmaOrderRepository, CacheServiceImpl cacheService, DataReportUtil dataReportUtil, ErrorReporter errorReporter) { + public BanmaOrderServiceImpl(BanmaOrderRepository banmaOrderRepository, CacheService cacheService, DataReportUtil dataReportUtil, ErrorReporter errorReporter) { this.banmaOrderRepository = banmaOrderRepository; this.cacheService = cacheService; this.dataReportUtil = dataReportUtil; @@ -233,9 +235,6 @@ public class BanmaOrderServiceImpl { return result; } - /** - * 提取子订单字段 - */ private void extractSubOrderFields(Map simplifiedOrder, Map subOrder) { String[] basicFields = {"orderedAt", "timeSinceOrder", "createdAt", "poTrackingNumber"}; String[] productFields = {"productTitle", "shopOrderNumber", "priceJpy", "productQuantity", "shippingFeeJpy", "productNumber", "serviceFee", "productImage"}; @@ -245,20 +244,11 @@ public class BanmaOrderServiceImpl { Arrays.stream(purchaseFields).forEach(field -> simplifiedOrder.put(field, subOrder.get(field))); } - - - - /** - * 从API获取物流信息 - */ private String fetchTrackingInfo(String trackingNumber) { - // 优先尝试佐川物流 Map trackInfoMap = (Map) new SagawaExpressSdk().getTrackingInfo(trackingNumber).get("trackInfo"); if (trackInfoMap != null) { return trackInfoMap.get("dateTime") + " " + trackInfoMap.get("office") + " " + trackInfoMap.get("status"); } - - // 斑马API ResponseEntity response = restTemplate.getForEntity(String.format(TRACKING_URL, trackingNumber), Map.class); return Optional.ofNullable(response.getBody()) .filter(body -> Integer.valueOf(0).equals(body.get("code"))) @@ -268,9 +258,4 @@ public class BanmaOrderServiceImpl { .map(track -> (String) track.get("track")) .orElse("暂无物流信息"); } - - - - - } diff --git a/erp_client_sb/src/main/java/com/tashow/erp/service/impl/CacheServiceImpl.java b/erp_client_sb/src/main/java/com/tashow/erp/service/impl/CacheServiceImpl.java deleted file mode 100644 index 5e176fe..0000000 --- a/erp_client_sb/src/main/java/com/tashow/erp/service/impl/CacheServiceImpl.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.tashow.erp.service.impl; - -import com.tashow.erp.entity.AuthTokenEntity; -import com.tashow.erp.repository.AuthTokenRepository; -import com.tashow.erp.service.ICacheService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.time.LocalDateTime; -import java.util.Optional; - -@Service -public class CacheServiceImpl implements ICacheService { - private static final Logger logger = LoggerFactory.getLogger(CacheServiceImpl.class); - - @Autowired - private AuthTokenRepository authTokenRepository; - - @Override - public void saveAuthToken(String service, String token, long expireTimeMillis) { - try { - Optional existing = authTokenRepository.findByServiceName(service); - AuthTokenEntity entity = existing.orElse(new AuthTokenEntity()); - entity.setServiceName(service); - entity.setToken(token); - entity.setExpireTime(LocalDateTime.now().plusSeconds(expireTimeMillis / 1000)); - authTokenRepository.save(entity); - } catch (Exception e) { - logger.error("保存认证令牌失败: {}", service, e); - } - } -} \ No newline at end of file diff --git a/erp_client_sb/src/main/java/com/tashow/erp/service/impl/GenmaiServiceImpl.java b/erp_client_sb/src/main/java/com/tashow/erp/service/impl/GenmaiServiceImpl.java index 04389bd..5156982 100644 --- a/erp_client_sb/src/main/java/com/tashow/erp/service/impl/GenmaiServiceImpl.java +++ b/erp_client_sb/src/main/java/com/tashow/erp/service/impl/GenmaiServiceImpl.java @@ -8,20 +8,15 @@ import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.chrome.ChromeOptions; -import com.tashow.erp.service.IGenmaiService; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.*; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import java.util.HashMap; import java.util.Map; -/** - * 跟卖精灵服务实现类 - * - * @author ruoyi - */ + @Service -public class GenmaiServiceImpl implements IGenmaiService { +public class GenmaiServiceImpl { @Value("${api.server.base-url}") private String serverApiUrl; @Value("${api.server.paths.getGenmaijlToken}") @@ -30,7 +25,6 @@ public class GenmaiServiceImpl implements IGenmaiService { private String updateGenmaijlToken; private final RestTemplate restTemplate = new RestTemplate(); ObjectMapper objectMapper = new ObjectMapper(); - @Override @SneakyThrows public void openGenmaiWebsite() { // 先关闭所有Chrome进程 diff --git a/erp_client_sb/src/main/java/com/tashow/erp/service/impl/RakutenCacheServiceImpl.java b/erp_client_sb/src/main/java/com/tashow/erp/service/impl/RakutenCacheServiceImpl.java index 4318a53..3cf1fde 100644 --- a/erp_client_sb/src/main/java/com/tashow/erp/service/impl/RakutenCacheServiceImpl.java +++ b/erp_client_sb/src/main/java/com/tashow/erp/service/impl/RakutenCacheServiceImpl.java @@ -2,7 +2,7 @@ package com.tashow.erp.service.impl; import com.tashow.erp.entity.RakutenProductEntity; import com.tashow.erp.model.RakutenProduct; import com.tashow.erp.repository.RakutenProductRepository; -import com.tashow.erp.service.IRakutenCacheService; +import com.tashow.erp.service.RakutenCacheService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -20,7 +20,7 @@ import java.util.stream.Collectors; */ @Slf4j @Service -public class RakutenCacheServiceImpl implements IRakutenCacheService { +public class RakutenCacheServiceImpl implements RakutenCacheService { @Autowired private RakutenProductRepository repository; diff --git a/erp_client_sb/src/main/java/com/tashow/erp/service/impl/RakutenScrapingServiceImpl.java b/erp_client_sb/src/main/java/com/tashow/erp/service/impl/RakutenScrapingServiceImpl.java index 5d2f870..e89e347 100644 --- a/erp_client_sb/src/main/java/com/tashow/erp/service/impl/RakutenScrapingServiceImpl.java +++ b/erp_client_sb/src/main/java/com/tashow/erp/service/impl/RakutenScrapingServiceImpl.java @@ -132,30 +132,24 @@ public class RakutenScrapingServiceImpl implements RakutenScrapingService { } } - /** - * 获取最新的产品数据用于前端展示 - */ @Override public List> getLatestProductsForDisplay() { return rakutenProductRepository.findLatestProducts().stream().map(entity -> { Map result = new HashMap<>(); - result.put("originalShopName", Optional.ofNullable(entity.getOriginalShopName()).orElse("")); - result.put("productUrl", Optional.ofNullable(entity.getProductUrl()).orElse("")); - result.put("imgUrl", Optional.ofNullable(entity.getImgUrl()).orElse("")); - result.put("productTitle", Optional.ofNullable(entity.getProductTitle()).orElse("")); - result.put("price", Optional.ofNullable(entity.getPrice()).orElse("")); - result.put("ranking", Optional.ofNullable(entity.getRanking()).orElse("")); - result.put("image1688Url", Optional.ofNullable(entity.getImage1688Url()).orElse("")); - result.put("detailUrl1688", Optional.ofNullable(entity.getDetailUrl1688()).orElse("")); - // 使用正确的实体字段 - result.put("mapRecognitionLink", Optional.ofNullable(entity.getMapRecognitionLink()).orElse("")); + result.put("originalShopName", entity.getOriginalShopName()); + result.put("productUrl", entity.getProductUrl()); + result.put("imgUrl", entity.getImgUrl()); + result.put("productTitle", entity.getProductTitle()); + result.put("price", entity.getPrice()); + result.put("ranking", entity.getRanking()); + result.put("image1688Url", entity.getImage1688Url()); + result.put("detailUrl1688", entity.getDetailUrl1688()); + result.put("mapRecognitionLink", entity.getMapRecognitionLink()); result.put("freight", entity.getFreight()); result.put("median", entity.getMedian()); - result.put("weight", Optional.ofNullable(entity.getWeight()).orElse("")); - result.put("skuPrice",entity.getSkuPriceJson()); + result.put("weight", entity.getWeight()); + result.put("skuPrice", entity.getSkuPriceJson()); return result; }).collect(Collectors.toList()); } - - } \ No newline at end of file diff --git a/erp_client_sb/src/main/java/com/tashow/erp/utils/ErrorReporter.java b/erp_client_sb/src/main/java/com/tashow/erp/utils/ErrorReporter.java index 9a0e82b..d67b73d 100644 --- a/erp_client_sb/src/main/java/com/tashow/erp/utils/ErrorReporter.java +++ b/erp_client_sb/src/main/java/com/tashow/erp/utils/ErrorReporter.java @@ -8,12 +8,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; -import com.tashow.erp.service.IAuthService; -/** - * 错误上报工具类 - 立即上报所有错误 - * - * @author ERP - */ +import com.tashow.erp.service.impl.AuthServiceImpl; + @Component public class ErrorReporter { @@ -21,7 +17,7 @@ public class ErrorReporter { private String serverUrl; @Autowired - private IAuthService authService; + private AuthServiceImpl authService; private final RestTemplate restTemplate = new RestTemplate(); diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ClientAccountController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ClientAccountController.java index 86e758a..949cff8 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ClientAccountController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ClientAccountController.java @@ -3,7 +3,6 @@ package com.ruoyi.web.controller.monitor; import java.util.Date; import java.util.List; import java.util.Map; -import java.util.HashMap; import com.ruoyi.common.annotation.Anonymous; import org.springframework.beans.factory.annotation.Autowired; @@ -58,6 +57,17 @@ public class ClientAccountController extends BaseController { @Autowired private ClientDeviceMapper clientDeviceMapper; + private AjaxResult checkDeviceLimit(String username, String deviceId, int deviceLimit) { + List userDevices = clientDeviceMapper.selectByUsername(username); + int userDevice = userDevices.size(); + boolean exists = userDevices.stream().anyMatch(d -> deviceId.equals(d.getDeviceId())); + if (exists) userDevice--; + if (userDevice >= deviceLimit) { + return AjaxResult.error("设备数量已达上限(" + deviceLimit + "个),请先移除其他设备"); + } + return null; + } + /** * 查询账号列表 */ @@ -140,15 +150,8 @@ public class ClientAccountController extends BaseController { return AjaxResult.error("账号已被停用"); } - // 检查设备数量限制 - int deviceLimit = account.getDeviceLimit(); - List userDevices = clientDeviceMapper.selectByUsername(username); - int userDevice = userDevices.size(); - boolean exists = userDevices.stream().anyMatch(d -> clientId.equals(d.getDeviceId())); - if (exists) userDevice--; - if (userDevice >= deviceLimit) { - return AjaxResult.error("设备数量已达上限(" + deviceLimit + "个),请先移除其他设备"); - } + AjaxResult limitCheck = checkDeviceLimit(username, clientId, account.getDeviceLimit()); + if (limitCheck != null) return limitCheck; String token = Jwts.builder() .setHeaderParam("kid", jwtRsaKeyService.getKeyId()) .setSubject(username) @@ -160,7 +163,6 @@ public class ClientAccountController extends BaseController { .signWith(SignatureAlgorithm.RS256, jwtRsaKeyService.getPrivateKey()) .compact(); - // 检查设备试用期(仅对trial账号生效) boolean deviceTrialExpired = false; if ("trial".equals(account.getAccountType())) { ClientDevice device = clientDeviceMapper.selectByDeviceIdAndUsername(clientId, username); @@ -169,14 +171,14 @@ public class ClientAccountController extends BaseController { && new Date().after(device.getTrialExpireTime()); } - Map data = new HashMap<>(); - data.put("token", token); - data.put("permissions", account.getPermissions()); - data.put("accountName", account.getAccountName()); - data.put("expireTime", account.getExpireTime()); - data.put("accountType", account.getAccountType()); - data.put("deviceTrialExpired", deviceTrialExpired); - return AjaxResult.success(data); + return AjaxResult.success(Map.of( + "token", token, + "permissions", account.getPermissions(), + "accountName", account.getAccountName(), + "expireTime", account.getExpireTime(), + "accountType", account.getAccountType(), + "deviceTrialExpired", deviceTrialExpired + )); } /** * 验证token @@ -202,7 +204,6 @@ public class ClientAccountController extends BaseController { clientAccountService.updateClientAccount(account); } - // 检查设备试用期(仅对trial账号生效) boolean deviceTrialExpired = false; if ("trial".equals(account.getAccountType())) { ClientDevice device = clientDeviceMapper.selectByDeviceIdAndUsername(clientId, username); @@ -211,14 +212,14 @@ public class ClientAccountController extends BaseController { && new Date().after(device.getTrialExpireTime()); } - Map result = new HashMap<>(); - result.put("username", username); - result.put("permissions", account.getPermissions()); - result.put("accountName", account.getAccountName()); - result.put("expireTime", account.getExpireTime()); - result.put("accountType", account.getAccountType()); - result.put("deviceTrialExpired", deviceTrialExpired); - return AjaxResult.success(result); + return AjaxResult.success(Map.of( + "username", username, + "permissions", account.getPermissions(), + "accountName", account.getAccountName(), + "expireTime", account.getExpireTime(), + "accountType", account.getAccountType(), + "deviceTrialExpired", deviceTrialExpired + )); } /** @@ -276,14 +277,14 @@ public class ClientAccountController extends BaseController { .signWith(SignatureAlgorithm.RS256, jwtRsaKeyService.getPrivateKey()) .compact(); - Map data = new HashMap<>(); - data.put("token", token); - data.put("permissions", clientAccount.getPermissions()); - data.put("accountName", clientAccount.getAccountName()); - data.put("expireTime", clientAccount.getExpireTime()); - data.put("accountType", clientAccount.getAccountType()); - data.put("deviceTrialExpired", false); - return AjaxResult.success(data); + return AjaxResult.success(Map.of( + "token", token, + "permissions", clientAccount.getPermissions(), + "accountName", clientAccount.getAccountName(), + "expireTime", clientAccount.getExpireTime(), + "accountType", clientAccount.getAccountType(), + "deviceTrialExpired", false + )); } /** @@ -324,13 +325,10 @@ public class ClientAccountController extends BaseController { account.setUpdateBy(getUsername()); clientAccountService.updateClientAccount(account); - // 推送续费通知 sseHubService.sendEventToAllDevices(account.getUsername(), "VIP_RENEWED", "{\"expireTime\":\"" + newExpireTime + "\"}"); - Map result = new HashMap<>(); - result.put("expireTime", newExpireTime); - return AjaxResult.success(result); + return AjaxResult.success(Map.of("expireTime", newExpireTime)); } } \ No newline at end of file diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/ClientDeviceController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/ClientDeviceController.java index 8a9c065..656e18a 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/ClientDeviceController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/ClientDeviceController.java @@ -1,7 +1,6 @@ package com.ruoyi.web.controller.system; import com.ruoyi.common.annotation.Anonymous; import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.utils.ip.IpUtils; import com.ruoyi.system.domain.ClientDevice; import com.ruoyi.system.mapper.ClientDeviceMapper; import com.ruoyi.system.mapper.ClientAccountMapper; @@ -10,7 +9,6 @@ import com.ruoyi.web.sse.SseHubService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; -import java.util.HashMap; import java.util.List; import java.util.Map; @@ -24,13 +22,19 @@ public class ClientDeviceController { private ClientAccountMapper clientAccountMapper; @Autowired private SseHubService sseHubService; + private AjaxResult checkDeviceLimit(String username, String deviceId) { + ClientAccount account = clientAccountMapper.selectClientAccountByUsername(username); + int deviceLimit = (account != null && account.getDeviceLimit() != null) ? account.getDeviceLimit() : 3; + List userDevices = clientDeviceMapper.selectByUsername(username); + int userDevice = userDevices.size(); + boolean deviceExists = userDevices.stream().anyMatch(d -> deviceId.equals(d.getDeviceId())); + if (deviceExists) userDevice--; + if (userDevice >= deviceLimit) { + return AjaxResult.error("设备数量已达上限(" + deviceLimit + "个),请先移除其他设备"); + } + return null; + } - /** - * 查询设备配额与已使用数量 - * - * @param username 用户名,为空时返回0 - * @return 配额信息 - */ @GetMapping("/quota") public AjaxResult quota(@RequestParam(value = "username", required = false) String username) { List all = clientDeviceMapper.selectByUsername(username); @@ -40,10 +44,7 @@ public class ClientDeviceController { } ClientAccount account = clientAccountMapper.selectClientAccountByUsername(username); int limit = (account != null && account.getDeviceLimit() != null) ? account.getDeviceLimit() : 3; - Map map = new HashMap<>(); - map.put("limit", limit); - map.put("used", used); - return AjaxResult.success(map); + return AjaxResult.success(Map.of("limit", limit, "used", used)); } /** * 按用户名查询设备列表(最近活动优先) @@ -70,16 +71,8 @@ public class ClientDeviceController { String os = device.getOs(); String deviceName = username + "@" + ip + " (" + os + ")"; - // 检查设备数量限制 - ClientAccount account = clientAccountMapper.selectClientAccountByUsername(username); - int deviceLimit = (account != null && account.getDeviceLimit() != null) ? account.getDeviceLimit() : 3; - List userDevices = clientDeviceMapper.selectByUsername(username); - int userDevice = userDevices.size(); - boolean deviceExists = userDevices.stream().anyMatch(d -> deviceId.equals(d.getDeviceId())); - if (deviceExists) userDevice--; - if (userDevice >= deviceLimit) { - return AjaxResult.error("设备数量已达上限(" + deviceLimit + "个),请先移除其他设备"); - } + AjaxResult limitCheck = checkDeviceLimit(username, deviceId); + if (limitCheck != null) return limitCheck; ClientDevice exists = clientDeviceMapper.selectByDeviceIdAndUsername(deviceId, username); if (exists == null) { diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/GenmaijlController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/GenmaijlController.java deleted file mode 100644 index 13a2331..0000000 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/GenmaijlController.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.ruoyi.web.controller.tool; - -import com.ruoyi.common.annotation.Anonymous; -import com.ruoyi.common.core.redis.RedisCache; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@Anonymous -public class GenmaijlController { - @Autowired - RedisCache redisCache; - @GetMapping("/getToken") - public String getToken(){ - return redisCache.getCacheObject("genmaijlToken"); - } - - @PostMapping("/saveToken") - public int saveToken(@RequestBody String token){ - redisCache.setCacheObject("genmaijlToken", token); - return 1; - } - - -}