From 0a2e896962ad370bb5b44007d247df13ff1bd7a9 Mon Sep 17 00:00:00 2001 From: ZiJIe <17738440858@163.com> Date: Tue, 24 Jun 2025 18:27:57 +0800 Subject: [PATCH] 222 --- .../main/java/com/ruoyi/RuoYiApplication.java | 60 +++--- .../controller/tool/WebMagicController.java | 3 +- ruoyi-ui/.env.development | 6 +- ruoyi-ui/.env.production | 4 +- ruoyi-ui/.env.staging | 4 +- ruoyi-ui/package.json | 2 +- ruoyi-ui/src/views/prod/products/index.vue | 180 +++++++++--------- ruoyi-ui/vue.config.js | 2 +- 8 files changed, 131 insertions(+), 130 deletions(-) diff --git a/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java index e3c56ee5..32eb6f1d 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java @@ -1,30 +1,30 @@ -package com.ruoyi; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; - -/** - * 启动程序 - * - * @author ruoyi - */ -@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }) -public class RuoYiApplication -{ - public static void main(String[] args) - { - // System.setProperty("spring.devtools.restart.enabled", "false"); - SpringApplication.run(RuoYiApplication.class, args); - System.out.println("(♥◠‿◠)ノ゙ 若依启动成功 ლ(´ڡ`ლ)゙ \n" + - " .-------. ____ __ \n" + - " | _ _ \\ \\ \\ / / \n" + - " | ( ' ) | \\ _. / ' \n" + - " |(_ o _) / _( )_ .' \n" + - " | (_,_).' __ ___(_ o _)' \n" + - " | |\\ \\ | || |(_,_)' \n" + - " | | \\ `' /| `-' / \n" + - " | | \\ / \\ / \n" + - " ''-' `'-' `-..-' "); - } -} +package com.ruoyi; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; + +/** + * 启动程序 + * + * @author ruoyi + */ +@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }) +public class RuoYiApplication +{ + public static void main(String[] args) + { + // System.setProperty("spring.devtools.restart.enabled", "false"); + SpringApplication.run(RuoYiApplication.class, args); + System.out.println("(♥◠‿◠)ノ゙ 若依启动成功 ლ(´ڡ`ლ)゙ \n" + + " .-------. ____ __ \n" + + " | _ _ \\ \\ \\ / / \n" + + " | ( ' ) | \\ _. / ' \n" + + " |(_ o _) / _( )_ .' \n" + + " | (_,_).' __ ___(_ o _)' \n" + + " | |\\ \\ | || |(_,_)' \n" + + " | | \\ `' /| `-' / \n" + + " | | \\ / \\ / \n" + + " ''-' `'-' `-..-' "); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/WebMagicController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/WebMagicController.java index 586ba768..44a67018 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/WebMagicController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/WebMagicController.java @@ -97,7 +97,7 @@ public class WebMagicController extends BaseController implements PageProcessor @SuppressWarnings("unchecked") private void loadProxyConfig() { try { - // File configFile = ResourceUtils.getFile("classpath:test_proxy.yml"); + //File configFile = ResourceUtils.getFile("classpath:test_proxy.yml"); File configFile = new File("/www/java_mall/erp/config/test_proxy.yml"); if (configFile.exists()) { Yaml yaml = new Yaml(); @@ -168,6 +168,7 @@ public class WebMagicController extends BaseController implements PageProcessor @Override public void process(Page page) { try { + System.out.println("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); Html html = page.getHtml(); String priceSymbol = html.xpath("//span[@class='a-price-symbol']/text()").toString(); String priceWhole = html.xpath("//span[@class='a-price-whole']/text()").toString(); diff --git a/ruoyi-ui/.env.development b/ruoyi-ui/.env.development index 18b2a3ed..d99f66ac 100644 --- a/ruoyi-ui/.env.development +++ b/ruoyi-ui/.env.development @@ -1,11 +1,11 @@ # 页面标题 -VUE_APP_TITLE = 若依管理系统 +VUE_APP_TITLE =ERP管理系统 # 开发环境配置 ENV = 'development' -# 若依管理系统/开发环境 -VUE_APP_BASE_API = '/dev-api' +# ERP管理系统/开发环境 +VUE_APP_BASE_API = 'http://192.168.1.89:8080' # 路由懒加载 VUE_CLI_BABEL_TRANSPILE_MODULES = true diff --git a/ruoyi-ui/.env.production b/ruoyi-ui/.env.production index 7cddf50b..35ecb89c 100644 --- a/ruoyi-ui/.env.production +++ b/ruoyi-ui/.env.production @@ -1,8 +1,8 @@ # 页面标题 -VUE_APP_TITLE = 若依管理系统 +VUE_APP_TITLE = ERP管理系统 # 生产环境配置 ENV = 'production' -# 若依管理系统/生产环境 +# ERP管理系统/生产环境 VUE_APP_BASE_API = 'https://erp.tashowz.com' diff --git a/ruoyi-ui/.env.staging b/ruoyi-ui/.env.staging index 730af342..2667aa96 100644 --- a/ruoyi-ui/.env.staging +++ b/ruoyi-ui/.env.staging @@ -1,5 +1,5 @@ # 页面标题 -VUE_APP_TITLE = 若依管理系统 +VUE_APP_TITLE = ERP管理系统 BABEL_ENV = production @@ -8,5 +8,5 @@ NODE_ENV = production # 测试环境配置 ENV = 'staging' -# 若依管理系统/测试环境 +# ERP管理系统/测试环境 VUE_APP_BASE_API = '/stage-api' diff --git a/ruoyi-ui/package.json b/ruoyi-ui/package.json index 0c89da88..c1f88232 100644 --- a/ruoyi-ui/package.json +++ b/ruoyi-ui/package.json @@ -1,7 +1,7 @@ { "name": "ruoyi", "version": "3.9.0", - "description": "若依管理系统", + "description": "ERP管理系统", "author": "若依", "license": "MIT", "scripts": { diff --git a/ruoyi-ui/src/views/prod/products/index.vue b/ruoyi-ui/src/views/prod/products/index.vue index 6c2a7630..1750e014 100644 --- a/ruoyi-ui/src/views/prod/products/index.vue +++ b/ruoyi-ui/src/views/prod/products/index.vue @@ -40,7 +40,7 @@ class="action-button" >开始爬取 - +
已导入 {{asinList.length}} 个ASIN @@ -59,13 +59,13 @@
- +
- - @@ -142,11 +142,11 @@ > - -
{{ getCountryFlag(item.name) }} - @@ -269,8 +269,8 @@ export default { return this.proxyNodes; } const keyword = this.proxySearchKeyword.toLowerCase(); - return this.proxyNodes.filter(proxy => - proxy.name.toLowerCase().includes(keyword) || + return this.proxyNodes.filter(proxy => + proxy.name.toLowerCase().includes(keyword) || proxy.server.toLowerCase().includes(keyword) ); } @@ -291,7 +291,7 @@ export default { { key: 'amazon_products_proxy', target: 'currentProxy' }, { key: 'amazon_products_proxy_delays', target: 'cachedDelays' } ]; - + items.forEach(item => { const data = localStorage.getItem(item.key); if (data) { @@ -307,7 +307,7 @@ export default { this.clearCache(); } }, - + /** 保存数据到本地缓存 */ saveToCache() { try { @@ -324,7 +324,7 @@ export default { console.error('保存数据到缓存失败:', error); } }, - + /** 保存代理延迟数据到本地缓存 */ saveProxyDelaysToCache() { try { @@ -338,7 +338,7 @@ export default { status: node.status, timestamp: new Date().getTime() })); - + if (delayData.length) { const testJson = JSON.stringify(delayData); @@ -349,10 +349,10 @@ export default { console.error('保存代理延迟数据到缓存失败:', error); } }, - + /** 清空缓存数据 */ clearCache() { - ['amazon_products_data', 'amazon_products_asin_list', + ['amazon_products_data', 'amazon_products_asin_list', 'amazon_products_proxy', 'amazon_products_proxy_delays'].forEach(key => { localStorage.removeItem(key); }); @@ -370,19 +370,19 @@ export default { }; return styles[type.toLowerCase()] || ''; }, - + /** 获取代理颜色 */ getProxyColor(index) { return ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C', '#909399'][index % 5]; }, - + /** 选择代理 */ selectProxy(name) { if (!this.loadingProxy && name) { this.selectedProxy = name; } }, - + /** 加载代理节点列表 */ loadProxyNodes() { this.loading = true; @@ -393,12 +393,12 @@ export default { this.loading = false; if (response.code === 200) { this.proxyNodes = response.data || []; - + if (this.proxyNodes.length) { if (this.currentProxy) { this.selectedProxy = this.currentProxy; } - + this.restoreCachedDelays(); } } else { @@ -408,13 +408,13 @@ export default { this.loading = false; }); }, - + restoreCachedDelays() { if (!this.cachedDelays?.length || !this.proxyNodes?.length) return; - + const now = new Date().getTime(); const oneDay = 24 * 60 * 60 * 1000; - + this.cachedDelays.forEach(cachedItem => { if (cachedItem?.timestamp && (now - cachedItem.timestamp) < oneDay) { const proxyNode = this.proxyNodes.find(p => p.name === cachedItem.name); @@ -425,7 +425,7 @@ export default { } }); }, - + /** 打开代理选择对话框 */ openProxyDialog() { this.tempSelectedProxy = this.selectedProxy; @@ -440,11 +440,11 @@ export default { this.proxyDialog.open = false; } }, - + /** 切换代理节点 */ handleProxyChange(proxyName) { if (!proxyName) return; - + this.loadingProxy = true; request({ url: '/tool/webmagic/proxy/set', @@ -453,7 +453,7 @@ export default { }).then(response => { this.loadingProxy = false; this.proxyDialog.open = false; - + if (response.code === 200) { this.currentProxy = proxyName; this.saveToCache(); @@ -467,11 +467,11 @@ export default { this.selectedProxy = this.currentProxy; }); }, - + /** 获取国家/地区旗帜emoji */ getCountryFlag(proxyName) { if (!proxyName) return '🌍'; - + const lowerName = proxyName.toLowerCase(); const flags = { 'hong kong': '🇭🇰', 'hk': '🇭🇰', '🇭🇰': '🇭🇰', @@ -492,7 +492,7 @@ export default { 'canada': '🇨🇦', 'ca': '🇨🇦', '🇨🇦': '🇨🇦', 'malaysia': '🇲🇾', 'my': '🇲🇾', '🇲🇾': '🇲🇾' }; - + const matchedKey = Object.keys(flags).find(key => lowerName.includes(key)); return matchedKey ? flags[matchedKey] : '🌍'; }, @@ -503,25 +503,25 @@ export default { return proxyName.replace(/^[\uD800-\uDBFF][\uDC00-\uDFFF]\s*/, '') .replace(/^\s*(vn|jp|hk|tw|sg|us|kr|in|ph|id|th|de|fr|gb|ca|my)\s+/i, ''); }, - + /** 导入按钮操作 */ handleImport() { this.upload.title = "导入ASIN"; this.upload.open = true; }, - + /** 进度条格式化 */ progressFormat(percentage) { return `${this.crawlProgress.current}/${this.crawlProgress.total}`; }, - + /** 获取进度条状态 */ getProgressStatus() { if (this.crawlProgress.percentage >= 100) return 'success'; if (this.crawlProgress.percentage < 0) return 'exception'; - return ''; + return ''; }, - + /** 下载模板操作 */ importTemplate() { // 创建模板数据 @@ -533,7 +533,7 @@ export default { ]; exportExcel(data, '亚马逊产品信息模板', '.et'); }, - + // 文件变更处理 handleFileChange(file) { // 验证文件类型 @@ -544,11 +544,11 @@ export default { this.$refs.upload.clearFiles(); return false; } - + // 保存当前选择的文件 this.selectedFile = file.raw; }, - + // 提交文件表单 submitFileForm() { if (!this.selectedFile) { @@ -563,23 +563,23 @@ export default { this.$message.error('导入数据为空'); return; } - + // 第一行是标题,从第二行开始 const asinList = data.slice(1) .map(row => row[0]) .filter(asin => asin && typeof asin === 'string' && asin.trim() !== ''); - + if (asinList.length === 0) { this.$message.error('未找到有效的ASIN数据'); return; } - + this.asinList = asinList; this.$message.success(`成功解析到${this.asinList.length}个ASIN`); - + // 保存ASIN列表到缓存 this.saveToCache(); - + // 关闭对话框并清除文件选择 this.upload.open = false; this.$refs.upload && this.$refs.upload.clearFiles(); @@ -593,44 +593,44 @@ export default { this.$message.error('处理文件失败: ' + (error.message || error)); } }, - + // 处理爬取 handleCrawl() { if (!this.asinList.length) { this.$message.warning("请先导入ASIN列表"); return; } - + if (!this.currentProxy) { this.startCrawl(); // 直接开始爬取,不弹确认框 } else { this.startCrawl(); } }, - + // 开始爬取 startCrawl() { this.crawling = true; this.loading = true; - + // 初始化爬取进度 this.crawlProgress = { total: this.asinList.length, current: 0, percentage: 0 }; - + // 分批爬取,每批2个ASIN const batchSize = 2; this.productData = []; // 清空之前的数据 - + // 清空缓存中的产品数据 localStorage.removeItem('amazon_products_data'); - + // 开始分批爬取 this.batchCrawl(this.asinList, 0, batchSize); }, - + // 分批爬取方法 batchCrawl(asinList, startIndex, batchSize) { if (startIndex >= asinList.length) { @@ -641,26 +641,26 @@ export default { this.saveToCache(); return; } - + // 计算当前批次的结束索引 const endIndex = Math.min(startIndex + batchSize, asinList.length); // 获取当前批次的ASIN列表 const currentBatch = asinList.slice(startIndex, endIndex); - + // 更新进度信息 this.crawlProgress.current = startIndex; this.crawlProgress.percentage = Math.floor((startIndex / this.crawlProgress.total) * 100); - + // 调用后端爬取接口 request({ url: '/tool/webmagic/batch', method: 'post', data: currentBatch, - timeout: 9000000 + timeout: 9000000 }).then(response => { if (response.code === 200) { this.productData = [...this.productData, ...response.data]; - + this.crawlProgress.current = endIndex; this.crawlProgress.percentage = Math.floor((endIndex / this.crawlProgress.total) * 100); this.batchCrawl(asinList, endIndex, batchSize); @@ -672,7 +672,7 @@ export default { }).catch(error => { console.error("爬取失败:", error); this.$message.error("爬取失败: " + (error.message || error)); - + if (error.message && error.message.includes('timeout')) { this.$message.warning("当前批次请求超时,将尝试继续下一批"); @@ -690,33 +690,33 @@ export default { } }); }, - + // 导出Excel handleExport() { if (!this.productData.length) { this.$message.warning("没有数据可导出"); return; } - + const data = [ ['ASIN', '卖家/配送方', '当前售价'] ]; - + this.productData.forEach(item => { const seller = item.seller || ''; const shipper = item.shipper ? (item.shipper !== item.seller ? `配送方: ${item.shipper}` : '') : ''; const sellerInfo = shipper ? `${seller} (${shipper})` : seller; - + data.push([ item.asin || '', sellerInfo, item.price || '' ]); }); - + exportExcel(data, '亚马逊产品信息', '.et'); }, - + /** 测试代理延迟 */ testProxyDelay() { if (!this.filteredProxyNodes?.length) { @@ -726,29 +726,29 @@ export default { this.startProxyTest(); // 直接开始测试,不弹确认框 }, - + /** 开始测试代理节点 */ startProxyTest() { this.testingDelay = true; const proxyNames = this.filteredProxyNodes.map(item => item.name); - + this.proxyNodes.forEach(proxy => { if (proxyNames.includes(proxy.name)) { proxy.delay = undefined; proxy.testing = true; } }); - + const batches = []; const batchSize = 10; - + for (let i = 0; i < proxyNames.length; i += batchSize) { batches.push(proxyNames.slice(i, i + batchSize)); } - + this.testNextBatch(batches, 0); }, - + /** 测试下一批代理节点 */ testNextBatch(batches, batchIndex) { if (batchIndex >= batches.length) { @@ -757,7 +757,7 @@ export default { this.saveProxyDelaysToCache(); return; } - + request({ url: '/tool/webmagic/proxy/test', method: 'post', @@ -776,10 +776,10 @@ export default { this.handleTestError(error.message || '网络错误', batches, batchIndex); }); }, - + updateProxyDelays(results) { if (!results?.length) return; - + results.forEach(result => { const proxyNode = this.proxyNodes.find(p => p.name === result.name); if (proxyNode) { @@ -789,11 +789,11 @@ export default { } }); }, - + /** 处理测试错误 */ handleTestError(errorMsg, batches, batchIndex) { console.error('测试代理延迟失败:', errorMsg); - + batches[batchIndex].forEach(proxyName => { const proxyNode = this.proxyNodes.find(p => p.name === proxyName); if (proxyNode?.testing) { @@ -802,13 +802,13 @@ export default { proxyNode.testing = false; } }); - + this.$message.warning('部分代理测试失败,继续测试下一批'); setTimeout(() => { this.testNextBatch(batches, batchIndex + 1); }, 500); }, - + /** 获取延迟样式类 */ getDelayClass(delay) { if (delay === undefined || delay < 0) return 'delay-error'; @@ -818,7 +818,7 @@ export default { if (delay < 1000) return 'delay-slow'; return 'delay-very-slow'; }, - + /** 格式化延迟显示 */ formatDelay(delay) { if (delay === undefined) return ''; diff --git a/ruoyi-ui/vue.config.js b/ruoyi-ui/vue.config.js index efb38fef..447a0268 100644 --- a/ruoyi-ui/vue.config.js +++ b/ruoyi-ui/vue.config.js @@ -7,7 +7,7 @@ function resolve(dir) { const CompressionPlugin = require('compression-webpack-plugin') -const name = process.env.VUE_APP_TITLE || '若依管理系统' // 网页标题 +const name = 'ERP管理系统' // 网页标题 const baseUrl = 'https://erp.tashowz.com' // 后端接口 //const baseUrl = 'http://43.136.31.205:8080'