diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index 68be33c..73d6507 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -16,7 +16,7 @@ ruoyi: # 开发环境配置 server: # 服务器的HTTP端口,默认为8080 - port: 8080 + port: 8090 servlet: # 应用的访问路径 context-path: / diff --git a/ruoyi-bid/src/main/java/com/ruoyi/bid/controller/BidInfoController.java b/ruoyi-bid/src/main/java/com/ruoyi/bid/controller/BidInfoController.java index 40231c8..3e40ab8 100644 --- a/ruoyi-bid/src/main/java/com/ruoyi/bid/controller/BidInfoController.java +++ b/ruoyi-bid/src/main/java/com/ruoyi/bid/controller/BidInfoController.java @@ -34,17 +34,6 @@ public class BidInfoController extends BaseController @Autowired private IBidInfoService bidInfoService; -/* *//** - * 查询招标信息列表 - *//* - @PreAuthorize("@ss.hasPermi('bid:info:list')") - @GetMapping("/select") - public TableDataInfo select() - { - startPage(); - List list = bidInfoService.selectBidInfoList(); - return getDataTable(list); - }*/ /** * 查询招标信息列表 */ diff --git a/ruoyi-bid/src/main/java/com/ruoyi/bid/controller/BidSiteController.java b/ruoyi-bid/src/main/java/com/ruoyi/bid/controller/BidSiteController.java new file mode 100644 index 0000000..3792d55 --- /dev/null +++ b/ruoyi-bid/src/main/java/com/ruoyi/bid/controller/BidSiteController.java @@ -0,0 +1,104 @@ +package com.ruoyi.bid.controller; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.security.access.prepost.PreAuthorize; +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.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.bid.domain.BidSite; +import com.ruoyi.bid.service.IBidSiteService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 常用网站Controller + * + * @author ruoyi + * @date 2025-12-09 + */ +@RestController +@RequestMapping("/bid/site") +public class BidSiteController extends BaseController +{ + @Autowired + private IBidSiteService bidSiteService; + + /** + * 查询常用网站列表 + */ + @PreAuthorize("@ss.hasPermi('bid:site:list')") + @GetMapping("/list") + public TableDataInfo list(BidSite bidSite) + { + startPage(); + List list = bidSiteService.selectBidSiteList(bidSite); + return getDataTable(list); + } + + /** + * 导出常用网站列表 + */ + @PreAuthorize("@ss.hasPermi('bid:site:export')") + @Log(title = "常用网站", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HttpServletResponse response, BidSite bidSite) + { + List list = bidSiteService.selectBidSiteList(bidSite); + ExcelUtil util = new ExcelUtil(BidSite.class); + util.exportExcel(response, list, "常用网站数据"); + } + + /** + * 获取常用网站详细信息 + */ + @PreAuthorize("@ss.hasPermi('bid:site:query')") + @GetMapping(value = "/{id}") + public AjaxResult getInfo(@PathVariable("id") Long id) + { + return success(bidSiteService.selectBidSiteById(id)); + } + + /** + * 新增常用网站 + */ + @PreAuthorize("@ss.hasPermi('bid:site:add')") + @Log(title = "常用网站", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody BidSite bidSite) + { + return toAjax(bidSiteService.insertBidSite(bidSite)); + } + + /** + * 修改常用网站 + */ + @PreAuthorize("@ss.hasPermi('bid:site:edit')") + @Log(title = "常用网站", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody BidSite bidSite) + { + return toAjax(bidSiteService.updateBidSite(bidSite)); + } + + /** + * 删除常用网站 + */ + @PreAuthorize("@ss.hasPermi('bid:site:remove')") + @Log(title = "常用网站", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public AjaxResult remove(@PathVariable Long[] ids) + { + return toAjax(bidSiteService.deleteBidSiteByIds(ids)); + } +} diff --git a/ruoyi-bid/src/main/java/com/ruoyi/bid/domain/BidSite.java b/ruoyi-bid/src/main/java/com/ruoyi/bid/domain/BidSite.java new file mode 100644 index 0000000..79b7e57 --- /dev/null +++ b/ruoyi-bid/src/main/java/com/ruoyi/bid/domain/BidSite.java @@ -0,0 +1,83 @@ +package com.ruoyi.bid.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 常用网站对象 bid_site + * + * @author ruoyi + * @date 2025-12-09 + */ +public class BidSite extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** ID */ + private Long id; + + /** 网站名称 */ + @Excel(name = "网站名称") + private String siteName; + + /** url */ + @Excel(name = "url") + private String site; + + /** 收藏(0否1是) */ + @Excel(name = "收藏(0否1是)") + private String favorite; + + public void setId(Long id) + { + this.id = id; + } + + public Long getId() + { + return id; + } + + public void setSiteName(String siteName) + { + this.siteName = siteName; + } + + public String getSiteName() + { + return siteName; + } + + public void setSite(String site) + { + this.site = site; + } + + public String getSite() + { + return site; + } + + public void setFavorite(String favorite) + { + this.favorite = favorite; + } + + public String getFavorite() + { + return favorite; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("siteName", getSiteName()) + .append("site", getSite()) + .append("favorite", getFavorite()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/ruoyi-bid/src/main/java/com/ruoyi/bid/mapper/BidSiteMapper.java b/ruoyi-bid/src/main/java/com/ruoyi/bid/mapper/BidSiteMapper.java new file mode 100644 index 0000000..ad780c3 --- /dev/null +++ b/ruoyi-bid/src/main/java/com/ruoyi/bid/mapper/BidSiteMapper.java @@ -0,0 +1,61 @@ +package com.ruoyi.bid.mapper; + +import java.util.List; +import com.ruoyi.bid.domain.BidSite; + +/** + * 常用网站Mapper接口 + * + * @author ruoyi + * @date 2025-12-09 + */ +public interface BidSiteMapper +{ + /** + * 查询常用网站 + * + * @param id 常用网站主键 + * @return 常用网站 + */ + public BidSite selectBidSiteById(Long id); + + /** + * 查询常用网站列表 + * + * @param bidSite 常用网站 + * @return 常用网站集合 + */ + public List selectBidSiteList(BidSite bidSite); + + /** + * 新增常用网站 + * + * @param bidSite 常用网站 + * @return 结果 + */ + public int insertBidSite(BidSite bidSite); + + /** + * 修改常用网站 + * + * @param bidSite 常用网站 + * @return 结果 + */ + public int updateBidSite(BidSite bidSite); + + /** + * 删除常用网站 + * + * @param id 常用网站主键 + * @return 结果 + */ + public int deleteBidSiteById(Long id); + + /** + * 批量删除常用网站 + * + * @param ids 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteBidSiteByIds(Long[] ids); +} diff --git a/ruoyi-bid/src/main/java/com/ruoyi/bid/service/IBidSiteService.java b/ruoyi-bid/src/main/java/com/ruoyi/bid/service/IBidSiteService.java new file mode 100644 index 0000000..f7077f0 --- /dev/null +++ b/ruoyi-bid/src/main/java/com/ruoyi/bid/service/IBidSiteService.java @@ -0,0 +1,61 @@ +package com.ruoyi.bid.service; + +import java.util.List; +import com.ruoyi.bid.domain.BidSite; + +/** + * 常用网站Service接口 + * + * @author ruoyi + * @date 2025-12-09 + */ +public interface IBidSiteService +{ + /** + * 查询常用网站 + * + * @param id 常用网站主键 + * @return 常用网站 + */ + public BidSite selectBidSiteById(Long id); + + /** + * 查询常用网站列表 + * + * @param bidSite 常用网站 + * @return 常用网站集合 + */ + public List selectBidSiteList(BidSite bidSite); + + /** + * 新增常用网站 + * + * @param bidSite 常用网站 + * @return 结果 + */ + public int insertBidSite(BidSite bidSite); + + /** + * 修改常用网站 + * + * @param bidSite 常用网站 + * @return 结果 + */ + public int updateBidSite(BidSite bidSite); + + /** + * 批量删除常用网站 + * + * @param ids 需要删除的常用网站主键集合 + * @return 结果 + */ + public int deleteBidSiteByIds(Long[] ids); + + /** + * 删除常用网站信息 + * + * @param id 常用网站主键 + * @return 结果 + */ + public int deleteBidSiteById(Long id); +} diff --git a/ruoyi-bid/src/main/java/com/ruoyi/bid/service/impl/BidSiteServiceImpl.java b/ruoyi-bid/src/main/java/com/ruoyi/bid/service/impl/BidSiteServiceImpl.java new file mode 100644 index 0000000..9a394a1 --- /dev/null +++ b/ruoyi-bid/src/main/java/com/ruoyi/bid/service/impl/BidSiteServiceImpl.java @@ -0,0 +1,93 @@ +package com.ruoyi.bid.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.bid.mapper.BidSiteMapper; +import com.ruoyi.bid.domain.BidSite; +import com.ruoyi.bid.service.IBidSiteService; + +/** + * 常用网站Service业务层处理 + * + * @author ruoyi + * @date 2025-12-09 + */ +@Service +public class BidSiteServiceImpl implements IBidSiteService +{ + @Autowired + private BidSiteMapper bidSiteMapper; + + /** + * 查询常用网站 + * + * @param id 常用网站主键 + * @return 常用网站 + */ + @Override + public BidSite selectBidSiteById(Long id) + { + return bidSiteMapper.selectBidSiteById(id); + } + + /** + * 查询常用网站列表 + * + * @param bidSite 常用网站 + * @return 常用网站 + */ + @Override + public List selectBidSiteList(BidSite bidSite) + { + return bidSiteMapper.selectBidSiteList(bidSite); + } + + /** + * 新增常用网站 + * + * @param bidSite 常用网站 + * @return 结果 + */ + @Override + public int insertBidSite(BidSite bidSite) + { + return bidSiteMapper.insertBidSite(bidSite); + } + + /** + * 修改常用网站 + * + * @param bidSite 常用网站 + * @return 结果 + */ + @Override + public int updateBidSite(BidSite bidSite) + { + return bidSiteMapper.updateBidSite(bidSite); + } + + /** + * 批量删除常用网站 + * + * @param ids 需要删除的常用网站主键 + * @return 结果 + */ + @Override + public int deleteBidSiteByIds(Long[] ids) + { + return bidSiteMapper.deleteBidSiteByIds(ids); + } + + /** + * 删除常用网站信息 + * + * @param id 常用网站主键 + * @return 结果 + */ + @Override + public int deleteBidSiteById(Long id) + { + return bidSiteMapper.deleteBidSiteById(id); + } +} diff --git a/ruoyi-bid/src/main/java/com/ruoyi/bid/util/BidSystemMVP.java b/ruoyi-bid/src/main/java/com/ruoyi/bid/util/BidSystemMVP.java index 4e057c8..4a4c260 100644 --- a/ruoyi-bid/src/main/java/com/ruoyi/bid/util/BidSystemMVP.java +++ b/ruoyi-bid/src/main/java/com/ruoyi/bid/util/BidSystemMVP.java @@ -17,6 +17,7 @@ import java.util.List; public class BidSystemMVP { // ================= 配置区域 ================= + // 1. 正向关键词(只要包含这些,就是商机) private static final List POSITIVE_KEYWORDS = Arrays.asList("系统", "平台", "软件", "信息化", "大数据"); diff --git a/ruoyi-bid/src/main/java/com/ruoyi/bid/util/BidSystemMVP3.java b/ruoyi-bid/src/main/java/com/ruoyi/bid/util/BidSystemMVP3.java index 545b99a..468d923 100644 --- a/ruoyi-bid/src/main/java/com/ruoyi/bid/util/BidSystemMVP3.java +++ b/ruoyi-bid/src/main/java/com/ruoyi/bid/util/BidSystemMVP3.java @@ -13,11 +13,11 @@ import java.util.regex.Pattern; * 招投标系统 - 低仿真核心链路模型 * 模拟功能:抓取 -> 清洗 -> 智能筛选 -> 模拟报警 */ -public final class BidSystemMVP3 { +public class BidSystemMVP3 { // ================= 配置区域 ================= // 目标日期:实际使用时改成 LocalDate.now().format(...) // 这里写死 20251208 是为了配合您刚才看到的真实数据 - private static final String TARGET_DATE_STR = "20251208"; + private static final String TARGET_DATE_STR = "20251209"; // 基础 URL 模板 (注意 %s 占位符) private static final String BASE_URL = "http://www.ccgp.gov.cn/cggg/zygg/index%s.htm"; @@ -25,7 +25,7 @@ public final class BidSystemMVP3 { // 正则表达式:用于从 URL 中提取日期 (匹配 t20251208 这种格式) private static final Pattern DATE_PATTERN = Pattern.compile("t(\\d{8})_"); - public List getBidInfos(String url, Date nowDate){ + public static List getBidInfos(String url, Date nowDate){ List bidInfos = new ArrayList<>(); System.out.println("========== 系统启动:智能时间翻页模式 =========="); @@ -103,6 +103,7 @@ public final class BidSystemMVP3 { info.setLink(href); info.setTitle(title); info.setSourceSite(currentUrl); + bidInfos.add(info); } } else if (urlDate.compareTo(TARGET_DATE_STR) < 0) { // B. 比今天小 (是以前的) -> 触发熔断 @@ -140,117 +141,10 @@ public final class BidSystemMVP3 { } catch (Exception e) { e.printStackTrace(); } - return null; + return bidInfos; } - public static void main(String[] args) { - System.out.println("========== 系统启动:智能时间翻页模式 =========="); - System.out.println("目标日期:" + TARGET_DATE_STR); - - try (Playwright playwright = Playwright.create()) { - // 启动浏览器 - Browser browser = playwright.chromium().launch(new BrowserType.LaunchOptions() - .setChannel("chrome") // 如果报错改成 "msedge" - .setHeadless(false) - .setSlowMo(500)); - - Page page = browser.newPage(); - - int pageNum = 0; // 0 代表第一页(index.htm), 1 代表第二页(index_1.htm) - boolean keepRunning = true; - int totalCount = 0; - - while (keepRunning) { - // 1. 构造当前页 URL - String currentUrl; - if (pageNum == 0) { - currentUrl = String.format(BASE_URL, ""); // 第一页 - } else { - currentUrl = String.format(BASE_URL, "_" + pageNum); // index_1.htm - } - - System.out.println("\n>> [第 " + (pageNum + 1) + " 页] 正在访问: " + currentUrl); - - try { - page.navigate(currentUrl); - // 智能等待,不再死等 5 秒,而是等内容加载 - page.waitForLoadState(); - // 稍微缓冲一下,防止反爬 - page.waitForTimeout(2000); - - } catch (Exception e) { - System.err.println(" 页面访问失败,停止翻页。"); - break; - } - - // 2. 扫描本页所有链接 - Locator links = page.locator("a"); - int count = links.count(); - int todayCountInThisPage = 0; // 统计这一页有多少今天的 - - for (int i = 0; i < count; i++) { - Locator item = links.nth(i); - if (!item.isVisible()) continue; - - String href = item.getAttribute("href"); - String title = item.innerText().trim(); - - // 过滤无效链接 - if (href == null || title.length() < 5) continue; - // --- 核心:从 URL 提取日期 --- - // 链接长这样:./zbgg/202512/t20251208_25880773.htm - Matcher matcher = DATE_PATTERN.matcher(href); - - if (matcher.find()) { - String urlDate = matcher.group(1); // 提取出 20251208 - - // 逻辑判定 - if (urlDate.equals(TARGET_DATE_STR)) { - // A. 是今天的 -> 进一步关键词筛选 - if (shouldSave(title)) { - System.out.println("[★ 收录] " + title); - System.out.println(" 日期: " + urlDate + " | 链接: " + fixLink(href)); - totalCount++; - todayCountInThisPage++; - } - } else if (urlDate.compareTo(TARGET_DATE_STR) < 0) { - // B. 比今天小 (是以前的) -> 触发熔断 - // 注意:有时候置顶公告可能是旧的,所以我们不能遇到一个旧的就立刻停 - // 策略:如果这一页大部分都是旧的,或者连续遇到旧的,才停。 - // 这里为了简单,我们打印出来观察一下 - // System.out.println(" [旧闻] " + urlDate + " - " + title); - } - } - } - - // 3. 翻页决策 - if (todayCountInThisPage == 0 && pageNum > 0) { - // 如果这一页一条今天的数据都没有(且不是第一页),说明已经翻到旧数据区了 - System.out.println(">> 本页无今日数据,触发【时间熔断】,停止抓取!"); - keepRunning = false; - } else { - System.out.println(">> 本页分析完毕,准备翻下一页..."); - pageNum++; - - // 安全锁:防止无限翻页 (最多翻20页) - if (pageNum > 20) { - System.out.println(">> 达到最大页数限制,停止。"); - keepRunning = false; - } - } - } - - System.out.println("\n========== 采集结束 =========="); - System.out.println("共捕获今日 (" + TARGET_DATE_STR + ") 商机: " + totalCount + " 条"); - - // 停留 5 秒后关闭 - page.waitForTimeout(5000); - - } catch (Exception e) { - e.printStackTrace(); - } - } // 关键词筛选 private static boolean shouldSave(String title) { diff --git a/ruoyi-bid/src/main/resources/mapper/bid/BidSiteMapper.xml b/ruoyi-bid/src/main/resources/mapper/bid/BidSiteMapper.xml new file mode 100644 index 0000000..9f3d3fc --- /dev/null +++ b/ruoyi-bid/src/main/resources/mapper/bid/BidSiteMapper.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + select id, site_name, site, favorite, remark from bid_site + + + + + + + + insert into bid_site + + site_name, + site, + favorite, + remark, + + + #{siteName}, + #{site}, + #{favorite}, + #{remark}, + + + + + update bid_site + + site_name = #{siteName}, + site = #{site}, + favorite = #{favorite}, + remark = #{remark}, + + where id = #{id} + + + + delete from bid_site where id = #{id} + + + + delete from bid_site where id in + + #{id} + + + \ No newline at end of file diff --git a/ruoyi-ui/src/api/bid/site.js b/ruoyi-ui/src/api/bid/site.js new file mode 100644 index 0000000..e8bcd53 --- /dev/null +++ b/ruoyi-ui/src/api/bid/site.js @@ -0,0 +1,44 @@ +import request from '@/utils/request' + +// 查询常用网站列表 +export function listSite(query) { + return request({ + url: '/bid/site/list', + method: 'get', + params: query + }) +} + +// 查询常用网站详细 +export function getSite(id) { + return request({ + url: '/bid/site/' + id, + method: 'get' + }) +} + +// 新增常用网站 +export function addSite(data) { + return request({ + url: '/bid/site', + method: 'post', + data: data + }) +} + +// 修改常用网站 +export function updateSite(data) { + return request({ + url: '/bid/site', + method: 'put', + data: data + }) +} + +// 删除常用网站 +export function delSite(id) { + return request({ + url: '/bid/site/' + id, + method: 'delete' + }) +} diff --git a/ruoyi-ui/src/views/bid/site/index.vue b/ruoyi-ui/src/views/bid/site/index.vue new file mode 100644 index 0000000..5ed1b6e --- /dev/null +++ b/ruoyi-ui/src/views/bid/site/index.vue @@ -0,0 +1,278 @@ + + + diff --git a/ruoyi-ui/src/views/info/index.vue b/ruoyi-ui/src/views/info/index.vue new file mode 100644 index 0000000..095ace3 --- /dev/null +++ b/ruoyi-ui/src/views/info/index.vue @@ -0,0 +1,336 @@ + + +