diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 0e47785..0adbba2 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -37,9 +37,19 @@ com.casic + casic-job-quartz + ${extension.version} + + + com.casic casic-selenium-core ${extension.version} + + com.google.guava + guava + 30.1-jre + diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 0e47785..0adbba2 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -37,9 +37,19 @@ com.casic + casic-job-quartz + ${extension.version} + + + com.casic casic-selenium-core ${extension.version} + + com.google.guava + guava + 30.1-jre + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java new file mode 100644 index 0000000..9dc3950 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java @@ -0,0 +1,94 @@ +package com.casic.missiles.modular.system.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.BaseController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.system.model.ProductInfo; +import com.casic.missiles.modular.system.service.IProductInfoService; +import com.casic.missiles.modular.system.service.ISearchKeysService; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 商品信息管理控制器 + * + * @author dev + * @Date 2022-05-05 15:46:28 + */ +@Controller +@RequestMapping("/productInfo") +public class ProductInfoController extends BaseController { + @Resource + private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + + /** + * 获取商品信息管理列表 + */ + @RequestMapping(value = "/list") + @ResponseBody + public Object list(String condition) { + return productInfoService.list(null); + } + + /** + * 获取商品信息管理分页列表 + */ + @RequestMapping(value = "/listPage") + @ResponseBody + public Object listPage(String condition) { + Page page = PageFactory.defaultPage(); + QueryWrapper query = new QueryWrapper<>(); + List productInfos = productInfoService.searchDbProductPricePage(condition, page); + page.setRecords(productInfos); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 新增商品信息管理 + */ + @RequestMapping(value = "/add") + @ResponseBody + public Object add(ProductInfo productInfo) { + productInfoService.save(productInfo); + return ResponseData.success(); + } + + /** + * 删除商品信息管理 + */ + @RequestMapping(value = "/delete") + @ResponseBody + public Object delete(@RequestParam String productInfoId) { + productInfoService.removeById(productInfoId); + return ResponseData.success(); + } + + /** + * 修改商品信息管理 + */ + @RequestMapping(value = "/update") + @ResponseBody + public Object update(ProductInfo productInfo) { + productInfoService.updateById(productInfo); + return ResponseData.success(); + } + + /** + * 商品信息管理详情 + */ + @RequestMapping(value = "/detail/{productInfoId}") + @ResponseBody + public Object detail(@PathVariable("productInfoId") String productInfoId) { + return ResponseData.success(productInfoService.getById(productInfoId)); + } +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 0e47785..0adbba2 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -37,9 +37,19 @@ com.casic + casic-job-quartz + ${extension.version} + + + com.casic casic-selenium-core ${extension.version} + + com.google.guava + guava + 30.1-jre + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java new file mode 100644 index 0000000..9dc3950 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java @@ -0,0 +1,94 @@ +package com.casic.missiles.modular.system.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.BaseController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.system.model.ProductInfo; +import com.casic.missiles.modular.system.service.IProductInfoService; +import com.casic.missiles.modular.system.service.ISearchKeysService; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 商品信息管理控制器 + * + * @author dev + * @Date 2022-05-05 15:46:28 + */ +@Controller +@RequestMapping("/productInfo") +public class ProductInfoController extends BaseController { + @Resource + private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + + /** + * 获取商品信息管理列表 + */ + @RequestMapping(value = "/list") + @ResponseBody + public Object list(String condition) { + return productInfoService.list(null); + } + + /** + * 获取商品信息管理分页列表 + */ + @RequestMapping(value = "/listPage") + @ResponseBody + public Object listPage(String condition) { + Page page = PageFactory.defaultPage(); + QueryWrapper query = new QueryWrapper<>(); + List productInfos = productInfoService.searchDbProductPricePage(condition, page); + page.setRecords(productInfos); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 新增商品信息管理 + */ + @RequestMapping(value = "/add") + @ResponseBody + public Object add(ProductInfo productInfo) { + productInfoService.save(productInfo); + return ResponseData.success(); + } + + /** + * 删除商品信息管理 + */ + @RequestMapping(value = "/delete") + @ResponseBody + public Object delete(@RequestParam String productInfoId) { + productInfoService.removeById(productInfoId); + return ResponseData.success(); + } + + /** + * 修改商品信息管理 + */ + @RequestMapping(value = "/update") + @ResponseBody + public Object update(ProductInfo productInfo) { + productInfoService.updateById(productInfo); + return ResponseData.success(); + } + + /** + * 商品信息管理详情 + */ + @RequestMapping(value = "/detail/{productInfoId}") + @ResponseBody + public Object detail(@PathVariable("productInfoId") String productInfoId) { + return ResponseData.success(productInfoService.getById(productInfoId)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java index 78c1892..446be24 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java @@ -1,11 +1,14 @@ package com.casic.missiles.modular.system.controller; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.BaseController; import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.form.IdForms; import com.casic.missiles.model.response.ResponseData; import com.casic.missiles.modular.system.model.SearchKeys; +import com.casic.missiles.modular.system.service.IProductInfoService; import com.casic.missiles.modular.system.service.ISearchKeysService; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; @@ -24,7 +27,25 @@ @Resource private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + /** + * 获取关键字管理列表 + */ + @GetMapping(value = "/loadSearch") + @ResponseBody + public Object loadSearch(String condition) { + new Thread(){ + @Override + public void run() { + super.run(); + productInfoService.searchProducts(null); + } + }.start(); + + return ResponseData.success(); + } /** * 获取关键字管理列表 @@ -43,6 +64,10 @@ public Object listPage(String condition) { Page page = PageFactory.defaultPage(); QueryWrapper query = new QueryWrapper<>(); + if (StrUtil.isNotEmpty(condition)) { + query.like("keywords", condition); + } + page = searchKeysService.page(page, query); return ResponseData.success(super.packForBT(page)); } @@ -52,7 +77,7 @@ */ @PostMapping(value = "/add") @ResponseBody - public Object add(SearchKeys searchKeys) { + public Object add(@RequestBody SearchKeys searchKeys) { searchKeysService.save(searchKeys); return ResponseData.success(); } @@ -62,8 +87,8 @@ */ @PostMapping(value = "/delete") @ResponseBody - public Object delete(@RequestParam String searchKeysId) { - searchKeysService.removeById(searchKeysId); + public Object delete(@RequestBody IdForms searchKeysIds) { + searchKeysService.removeByIds(searchKeysIds.getIds()); return ResponseData.success(); } @@ -73,7 +98,7 @@ */ @PostMapping(value = "/update") @ResponseBody - public Object update(SearchKeys searchKeys) { + public Object update(@RequestBody SearchKeys searchKeys) { searchKeysService.updateById(searchKeys); return ResponseData.success(); } diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 0e47785..0adbba2 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -37,9 +37,19 @@ com.casic + casic-job-quartz + ${extension.version} + + + com.casic casic-selenium-core ${extension.version} + + com.google.guava + guava + 30.1-jre + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java new file mode 100644 index 0000000..9dc3950 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java @@ -0,0 +1,94 @@ +package com.casic.missiles.modular.system.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.BaseController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.system.model.ProductInfo; +import com.casic.missiles.modular.system.service.IProductInfoService; +import com.casic.missiles.modular.system.service.ISearchKeysService; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 商品信息管理控制器 + * + * @author dev + * @Date 2022-05-05 15:46:28 + */ +@Controller +@RequestMapping("/productInfo") +public class ProductInfoController extends BaseController { + @Resource + private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + + /** + * 获取商品信息管理列表 + */ + @RequestMapping(value = "/list") + @ResponseBody + public Object list(String condition) { + return productInfoService.list(null); + } + + /** + * 获取商品信息管理分页列表 + */ + @RequestMapping(value = "/listPage") + @ResponseBody + public Object listPage(String condition) { + Page page = PageFactory.defaultPage(); + QueryWrapper query = new QueryWrapper<>(); + List productInfos = productInfoService.searchDbProductPricePage(condition, page); + page.setRecords(productInfos); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 新增商品信息管理 + */ + @RequestMapping(value = "/add") + @ResponseBody + public Object add(ProductInfo productInfo) { + productInfoService.save(productInfo); + return ResponseData.success(); + } + + /** + * 删除商品信息管理 + */ + @RequestMapping(value = "/delete") + @ResponseBody + public Object delete(@RequestParam String productInfoId) { + productInfoService.removeById(productInfoId); + return ResponseData.success(); + } + + /** + * 修改商品信息管理 + */ + @RequestMapping(value = "/update") + @ResponseBody + public Object update(ProductInfo productInfo) { + productInfoService.updateById(productInfo); + return ResponseData.success(); + } + + /** + * 商品信息管理详情 + */ + @RequestMapping(value = "/detail/{productInfoId}") + @ResponseBody + public Object detail(@PathVariable("productInfoId") String productInfoId) { + return ResponseData.success(productInfoService.getById(productInfoId)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java index 78c1892..446be24 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java @@ -1,11 +1,14 @@ package com.casic.missiles.modular.system.controller; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.BaseController; import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.form.IdForms; import com.casic.missiles.model.response.ResponseData; import com.casic.missiles.modular.system.model.SearchKeys; +import com.casic.missiles.modular.system.service.IProductInfoService; import com.casic.missiles.modular.system.service.ISearchKeysService; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; @@ -24,7 +27,25 @@ @Resource private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + /** + * 获取关键字管理列表 + */ + @GetMapping(value = "/loadSearch") + @ResponseBody + public Object loadSearch(String condition) { + new Thread(){ + @Override + public void run() { + super.run(); + productInfoService.searchProducts(null); + } + }.start(); + + return ResponseData.success(); + } /** * 获取关键字管理列表 @@ -43,6 +64,10 @@ public Object listPage(String condition) { Page page = PageFactory.defaultPage(); QueryWrapper query = new QueryWrapper<>(); + if (StrUtil.isNotEmpty(condition)) { + query.like("keywords", condition); + } + page = searchKeysService.page(page, query); return ResponseData.success(super.packForBT(page)); } @@ -52,7 +77,7 @@ */ @PostMapping(value = "/add") @ResponseBody - public Object add(SearchKeys searchKeys) { + public Object add(@RequestBody SearchKeys searchKeys) { searchKeysService.save(searchKeys); return ResponseData.success(); } @@ -62,8 +87,8 @@ */ @PostMapping(value = "/delete") @ResponseBody - public Object delete(@RequestParam String searchKeysId) { - searchKeysService.removeById(searchKeysId); + public Object delete(@RequestBody IdForms searchKeysIds) { + searchKeysService.removeByIds(searchKeysIds.getIds()); return ResponseData.success(); } @@ -73,7 +98,7 @@ */ @PostMapping(value = "/update") @ResponseBody - public Object update(SearchKeys searchKeys) { + public Object update(@RequestBody SearchKeys searchKeys) { searchKeysService.updateById(searchKeys); return ResponseData.success(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java new file mode 100644 index 0000000..c3d1185 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.system.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.system.model.ProductInfo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 商品信息 Mapper 接口 + *

+ * + * @author stylefeng123 + * @since 2022-05-05 + */ +public interface ProductInfoMapper extends BaseMapper { + + /** + * 产品数据检索 + * + * @return 产品价格列表 + */ + List searchDbProductPricePage(@Param("keywords") String keywords, @Param("page") Page page); +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 0e47785..0adbba2 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -37,9 +37,19 @@ com.casic + casic-job-quartz + ${extension.version} + + + com.casic casic-selenium-core ${extension.version} + + com.google.guava + guava + 30.1-jre + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java new file mode 100644 index 0000000..9dc3950 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java @@ -0,0 +1,94 @@ +package com.casic.missiles.modular.system.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.BaseController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.system.model.ProductInfo; +import com.casic.missiles.modular.system.service.IProductInfoService; +import com.casic.missiles.modular.system.service.ISearchKeysService; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 商品信息管理控制器 + * + * @author dev + * @Date 2022-05-05 15:46:28 + */ +@Controller +@RequestMapping("/productInfo") +public class ProductInfoController extends BaseController { + @Resource + private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + + /** + * 获取商品信息管理列表 + */ + @RequestMapping(value = "/list") + @ResponseBody + public Object list(String condition) { + return productInfoService.list(null); + } + + /** + * 获取商品信息管理分页列表 + */ + @RequestMapping(value = "/listPage") + @ResponseBody + public Object listPage(String condition) { + Page page = PageFactory.defaultPage(); + QueryWrapper query = new QueryWrapper<>(); + List productInfos = productInfoService.searchDbProductPricePage(condition, page); + page.setRecords(productInfos); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 新增商品信息管理 + */ + @RequestMapping(value = "/add") + @ResponseBody + public Object add(ProductInfo productInfo) { + productInfoService.save(productInfo); + return ResponseData.success(); + } + + /** + * 删除商品信息管理 + */ + @RequestMapping(value = "/delete") + @ResponseBody + public Object delete(@RequestParam String productInfoId) { + productInfoService.removeById(productInfoId); + return ResponseData.success(); + } + + /** + * 修改商品信息管理 + */ + @RequestMapping(value = "/update") + @ResponseBody + public Object update(ProductInfo productInfo) { + productInfoService.updateById(productInfo); + return ResponseData.success(); + } + + /** + * 商品信息管理详情 + */ + @RequestMapping(value = "/detail/{productInfoId}") + @ResponseBody + public Object detail(@PathVariable("productInfoId") String productInfoId) { + return ResponseData.success(productInfoService.getById(productInfoId)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java index 78c1892..446be24 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java @@ -1,11 +1,14 @@ package com.casic.missiles.modular.system.controller; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.BaseController; import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.form.IdForms; import com.casic.missiles.model.response.ResponseData; import com.casic.missiles.modular.system.model.SearchKeys; +import com.casic.missiles.modular.system.service.IProductInfoService; import com.casic.missiles.modular.system.service.ISearchKeysService; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; @@ -24,7 +27,25 @@ @Resource private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + /** + * 获取关键字管理列表 + */ + @GetMapping(value = "/loadSearch") + @ResponseBody + public Object loadSearch(String condition) { + new Thread(){ + @Override + public void run() { + super.run(); + productInfoService.searchProducts(null); + } + }.start(); + + return ResponseData.success(); + } /** * 获取关键字管理列表 @@ -43,6 +64,10 @@ public Object listPage(String condition) { Page page = PageFactory.defaultPage(); QueryWrapper query = new QueryWrapper<>(); + if (StrUtil.isNotEmpty(condition)) { + query.like("keywords", condition); + } + page = searchKeysService.page(page, query); return ResponseData.success(super.packForBT(page)); } @@ -52,7 +77,7 @@ */ @PostMapping(value = "/add") @ResponseBody - public Object add(SearchKeys searchKeys) { + public Object add(@RequestBody SearchKeys searchKeys) { searchKeysService.save(searchKeys); return ResponseData.success(); } @@ -62,8 +87,8 @@ */ @PostMapping(value = "/delete") @ResponseBody - public Object delete(@RequestParam String searchKeysId) { - searchKeysService.removeById(searchKeysId); + public Object delete(@RequestBody IdForms searchKeysIds) { + searchKeysService.removeByIds(searchKeysIds.getIds()); return ResponseData.success(); } @@ -73,7 +98,7 @@ */ @PostMapping(value = "/update") @ResponseBody - public Object update(SearchKeys searchKeys) { + public Object update(@RequestBody SearchKeys searchKeys) { searchKeysService.updateById(searchKeys); return ResponseData.success(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java new file mode 100644 index 0000000..c3d1185 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.system.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.system.model.ProductInfo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 商品信息 Mapper 接口 + *

+ * + * @author stylefeng123 + * @since 2022-05-05 + */ +public interface ProductInfoMapper extends BaseMapper { + + /** + * 产品数据检索 + * + * @return 产品价格列表 + */ + List searchDbProductPricePage(@Param("keywords") String keywords, @Param("page") Page page); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml new file mode 100644 index 0000000..99c83ba --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + id, max_price AS maxPrice, min_price AS minPrice, description + + + + '%' || #{keywords}|| '%' + + + CONCAT('%',#{keywords},'%') + + diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 0e47785..0adbba2 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -37,9 +37,19 @@ com.casic + casic-job-quartz + ${extension.version} + + + com.casic casic-selenium-core ${extension.version} + + com.google.guava + guava + 30.1-jre + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java new file mode 100644 index 0000000..9dc3950 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java @@ -0,0 +1,94 @@ +package com.casic.missiles.modular.system.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.BaseController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.system.model.ProductInfo; +import com.casic.missiles.modular.system.service.IProductInfoService; +import com.casic.missiles.modular.system.service.ISearchKeysService; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 商品信息管理控制器 + * + * @author dev + * @Date 2022-05-05 15:46:28 + */ +@Controller +@RequestMapping("/productInfo") +public class ProductInfoController extends BaseController { + @Resource + private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + + /** + * 获取商品信息管理列表 + */ + @RequestMapping(value = "/list") + @ResponseBody + public Object list(String condition) { + return productInfoService.list(null); + } + + /** + * 获取商品信息管理分页列表 + */ + @RequestMapping(value = "/listPage") + @ResponseBody + public Object listPage(String condition) { + Page page = PageFactory.defaultPage(); + QueryWrapper query = new QueryWrapper<>(); + List productInfos = productInfoService.searchDbProductPricePage(condition, page); + page.setRecords(productInfos); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 新增商品信息管理 + */ + @RequestMapping(value = "/add") + @ResponseBody + public Object add(ProductInfo productInfo) { + productInfoService.save(productInfo); + return ResponseData.success(); + } + + /** + * 删除商品信息管理 + */ + @RequestMapping(value = "/delete") + @ResponseBody + public Object delete(@RequestParam String productInfoId) { + productInfoService.removeById(productInfoId); + return ResponseData.success(); + } + + /** + * 修改商品信息管理 + */ + @RequestMapping(value = "/update") + @ResponseBody + public Object update(ProductInfo productInfo) { + productInfoService.updateById(productInfo); + return ResponseData.success(); + } + + /** + * 商品信息管理详情 + */ + @RequestMapping(value = "/detail/{productInfoId}") + @ResponseBody + public Object detail(@PathVariable("productInfoId") String productInfoId) { + return ResponseData.success(productInfoService.getById(productInfoId)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java index 78c1892..446be24 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java @@ -1,11 +1,14 @@ package com.casic.missiles.modular.system.controller; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.BaseController; import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.form.IdForms; import com.casic.missiles.model.response.ResponseData; import com.casic.missiles.modular.system.model.SearchKeys; +import com.casic.missiles.modular.system.service.IProductInfoService; import com.casic.missiles.modular.system.service.ISearchKeysService; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; @@ -24,7 +27,25 @@ @Resource private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + /** + * 获取关键字管理列表 + */ + @GetMapping(value = "/loadSearch") + @ResponseBody + public Object loadSearch(String condition) { + new Thread(){ + @Override + public void run() { + super.run(); + productInfoService.searchProducts(null); + } + }.start(); + + return ResponseData.success(); + } /** * 获取关键字管理列表 @@ -43,6 +64,10 @@ public Object listPage(String condition) { Page page = PageFactory.defaultPage(); QueryWrapper query = new QueryWrapper<>(); + if (StrUtil.isNotEmpty(condition)) { + query.like("keywords", condition); + } + page = searchKeysService.page(page, query); return ResponseData.success(super.packForBT(page)); } @@ -52,7 +77,7 @@ */ @PostMapping(value = "/add") @ResponseBody - public Object add(SearchKeys searchKeys) { + public Object add(@RequestBody SearchKeys searchKeys) { searchKeysService.save(searchKeys); return ResponseData.success(); } @@ -62,8 +87,8 @@ */ @PostMapping(value = "/delete") @ResponseBody - public Object delete(@RequestParam String searchKeysId) { - searchKeysService.removeById(searchKeysId); + public Object delete(@RequestBody IdForms searchKeysIds) { + searchKeysService.removeByIds(searchKeysIds.getIds()); return ResponseData.success(); } @@ -73,7 +98,7 @@ */ @PostMapping(value = "/update") @ResponseBody - public Object update(SearchKeys searchKeys) { + public Object update(@RequestBody SearchKeys searchKeys) { searchKeysService.updateById(searchKeys); return ResponseData.success(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java new file mode 100644 index 0000000..c3d1185 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.system.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.system.model.ProductInfo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 商品信息 Mapper 接口 + *

+ * + * @author stylefeng123 + * @since 2022-05-05 + */ +public interface ProductInfoMapper extends BaseMapper { + + /** + * 产品数据检索 + * + * @return 产品价格列表 + */ + List searchDbProductPricePage(@Param("keywords") String keywords, @Param("page") Page page); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml new file mode 100644 index 0000000..99c83ba --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + id, max_price AS maxPrice, min_price AS minPrice, description + + + + '%' || #{keywords}|| '%' + + + CONCAT('%',#{keywords},'%') + + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml index 348f2a0..4f41b58 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml @@ -5,14 +5,14 @@ - + - id, keys, search_time AS searchTime, keep_days AS keepDays + id, keywords, search_time AS searchTime, keep_days AS keepDays diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 0e47785..0adbba2 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -37,9 +37,19 @@ com.casic + casic-job-quartz + ${extension.version} + + + com.casic casic-selenium-core ${extension.version} + + com.google.guava + guava + 30.1-jre + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java new file mode 100644 index 0000000..9dc3950 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java @@ -0,0 +1,94 @@ +package com.casic.missiles.modular.system.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.BaseController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.system.model.ProductInfo; +import com.casic.missiles.modular.system.service.IProductInfoService; +import com.casic.missiles.modular.system.service.ISearchKeysService; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 商品信息管理控制器 + * + * @author dev + * @Date 2022-05-05 15:46:28 + */ +@Controller +@RequestMapping("/productInfo") +public class ProductInfoController extends BaseController { + @Resource + private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + + /** + * 获取商品信息管理列表 + */ + @RequestMapping(value = "/list") + @ResponseBody + public Object list(String condition) { + return productInfoService.list(null); + } + + /** + * 获取商品信息管理分页列表 + */ + @RequestMapping(value = "/listPage") + @ResponseBody + public Object listPage(String condition) { + Page page = PageFactory.defaultPage(); + QueryWrapper query = new QueryWrapper<>(); + List productInfos = productInfoService.searchDbProductPricePage(condition, page); + page.setRecords(productInfos); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 新增商品信息管理 + */ + @RequestMapping(value = "/add") + @ResponseBody + public Object add(ProductInfo productInfo) { + productInfoService.save(productInfo); + return ResponseData.success(); + } + + /** + * 删除商品信息管理 + */ + @RequestMapping(value = "/delete") + @ResponseBody + public Object delete(@RequestParam String productInfoId) { + productInfoService.removeById(productInfoId); + return ResponseData.success(); + } + + /** + * 修改商品信息管理 + */ + @RequestMapping(value = "/update") + @ResponseBody + public Object update(ProductInfo productInfo) { + productInfoService.updateById(productInfo); + return ResponseData.success(); + } + + /** + * 商品信息管理详情 + */ + @RequestMapping(value = "/detail/{productInfoId}") + @ResponseBody + public Object detail(@PathVariable("productInfoId") String productInfoId) { + return ResponseData.success(productInfoService.getById(productInfoId)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java index 78c1892..446be24 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java @@ -1,11 +1,14 @@ package com.casic.missiles.modular.system.controller; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.BaseController; import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.form.IdForms; import com.casic.missiles.model.response.ResponseData; import com.casic.missiles.modular.system.model.SearchKeys; +import com.casic.missiles.modular.system.service.IProductInfoService; import com.casic.missiles.modular.system.service.ISearchKeysService; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; @@ -24,7 +27,25 @@ @Resource private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + /** + * 获取关键字管理列表 + */ + @GetMapping(value = "/loadSearch") + @ResponseBody + public Object loadSearch(String condition) { + new Thread(){ + @Override + public void run() { + super.run(); + productInfoService.searchProducts(null); + } + }.start(); + + return ResponseData.success(); + } /** * 获取关键字管理列表 @@ -43,6 +64,10 @@ public Object listPage(String condition) { Page page = PageFactory.defaultPage(); QueryWrapper query = new QueryWrapper<>(); + if (StrUtil.isNotEmpty(condition)) { + query.like("keywords", condition); + } + page = searchKeysService.page(page, query); return ResponseData.success(super.packForBT(page)); } @@ -52,7 +77,7 @@ */ @PostMapping(value = "/add") @ResponseBody - public Object add(SearchKeys searchKeys) { + public Object add(@RequestBody SearchKeys searchKeys) { searchKeysService.save(searchKeys); return ResponseData.success(); } @@ -62,8 +87,8 @@ */ @PostMapping(value = "/delete") @ResponseBody - public Object delete(@RequestParam String searchKeysId) { - searchKeysService.removeById(searchKeysId); + public Object delete(@RequestBody IdForms searchKeysIds) { + searchKeysService.removeByIds(searchKeysIds.getIds()); return ResponseData.success(); } @@ -73,7 +98,7 @@ */ @PostMapping(value = "/update") @ResponseBody - public Object update(SearchKeys searchKeys) { + public Object update(@RequestBody SearchKeys searchKeys) { searchKeysService.updateById(searchKeys); return ResponseData.success(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java new file mode 100644 index 0000000..c3d1185 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.system.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.system.model.ProductInfo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 商品信息 Mapper 接口 + *

+ * + * @author stylefeng123 + * @since 2022-05-05 + */ +public interface ProductInfoMapper extends BaseMapper { + + /** + * 产品数据检索 + * + * @return 产品价格列表 + */ + List searchDbProductPricePage(@Param("keywords") String keywords, @Param("page") Page page); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml new file mode 100644 index 0000000..99c83ba --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + id, max_price AS maxPrice, min_price AS minPrice, description + + + + '%' || #{keywords}|| '%' + + + CONCAT('%',#{keywords},'%') + + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml index 348f2a0..4f41b58 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml @@ -5,14 +5,14 @@ - + - id, keys, search_time AS searchTime, keep_days AS keepDays + id, keywords, search_time AS searchTime, keep_days AS keepDays diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java b/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java new file mode 100644 index 0000000..df0766c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java @@ -0,0 +1,38 @@ +package com.casic.missiles.modular.system.job; + +import cn.hutool.core.util.RandomUtil; +import com.casic.missiles.modular.system.service.IProductInfoService; +import lombok.SneakyThrows; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.math.BigDecimal; + +/** + * @ClassName QuartzJob + * @Description 依赖casic-job-quartz,并在CasicApplication上增加注解 @EnableScheduling + * @Author lwh + * @Date 2021/2/5 11:20 + * @Version 1.0 + */ +@Component +public class QuartzJob { + @Resource + private IProductInfoService productInfoService; + + /** + * + */ + @SneakyThrows + @Scheduled(cron = "0 0 10,14,16 * * ?") + public void execute() { + try { + Thread.sleep(RandomUtil.randomBigDecimal(new BigDecimal(2000)).intValue()); + System.out.println("-----Thread ID 每60秒执行一次"); + productInfoService.searchProducts(null); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 0e47785..0adbba2 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -37,9 +37,19 @@ com.casic + casic-job-quartz + ${extension.version} + + + com.casic casic-selenium-core ${extension.version} + + com.google.guava + guava + 30.1-jre + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java new file mode 100644 index 0000000..9dc3950 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java @@ -0,0 +1,94 @@ +package com.casic.missiles.modular.system.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.BaseController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.system.model.ProductInfo; +import com.casic.missiles.modular.system.service.IProductInfoService; +import com.casic.missiles.modular.system.service.ISearchKeysService; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 商品信息管理控制器 + * + * @author dev + * @Date 2022-05-05 15:46:28 + */ +@Controller +@RequestMapping("/productInfo") +public class ProductInfoController extends BaseController { + @Resource + private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + + /** + * 获取商品信息管理列表 + */ + @RequestMapping(value = "/list") + @ResponseBody + public Object list(String condition) { + return productInfoService.list(null); + } + + /** + * 获取商品信息管理分页列表 + */ + @RequestMapping(value = "/listPage") + @ResponseBody + public Object listPage(String condition) { + Page page = PageFactory.defaultPage(); + QueryWrapper query = new QueryWrapper<>(); + List productInfos = productInfoService.searchDbProductPricePage(condition, page); + page.setRecords(productInfos); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 新增商品信息管理 + */ + @RequestMapping(value = "/add") + @ResponseBody + public Object add(ProductInfo productInfo) { + productInfoService.save(productInfo); + return ResponseData.success(); + } + + /** + * 删除商品信息管理 + */ + @RequestMapping(value = "/delete") + @ResponseBody + public Object delete(@RequestParam String productInfoId) { + productInfoService.removeById(productInfoId); + return ResponseData.success(); + } + + /** + * 修改商品信息管理 + */ + @RequestMapping(value = "/update") + @ResponseBody + public Object update(ProductInfo productInfo) { + productInfoService.updateById(productInfo); + return ResponseData.success(); + } + + /** + * 商品信息管理详情 + */ + @RequestMapping(value = "/detail/{productInfoId}") + @ResponseBody + public Object detail(@PathVariable("productInfoId") String productInfoId) { + return ResponseData.success(productInfoService.getById(productInfoId)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java index 78c1892..446be24 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java @@ -1,11 +1,14 @@ package com.casic.missiles.modular.system.controller; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.BaseController; import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.form.IdForms; import com.casic.missiles.model.response.ResponseData; import com.casic.missiles.modular.system.model.SearchKeys; +import com.casic.missiles.modular.system.service.IProductInfoService; import com.casic.missiles.modular.system.service.ISearchKeysService; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; @@ -24,7 +27,25 @@ @Resource private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + /** + * 获取关键字管理列表 + */ + @GetMapping(value = "/loadSearch") + @ResponseBody + public Object loadSearch(String condition) { + new Thread(){ + @Override + public void run() { + super.run(); + productInfoService.searchProducts(null); + } + }.start(); + + return ResponseData.success(); + } /** * 获取关键字管理列表 @@ -43,6 +64,10 @@ public Object listPage(String condition) { Page page = PageFactory.defaultPage(); QueryWrapper query = new QueryWrapper<>(); + if (StrUtil.isNotEmpty(condition)) { + query.like("keywords", condition); + } + page = searchKeysService.page(page, query); return ResponseData.success(super.packForBT(page)); } @@ -52,7 +77,7 @@ */ @PostMapping(value = "/add") @ResponseBody - public Object add(SearchKeys searchKeys) { + public Object add(@RequestBody SearchKeys searchKeys) { searchKeysService.save(searchKeys); return ResponseData.success(); } @@ -62,8 +87,8 @@ */ @PostMapping(value = "/delete") @ResponseBody - public Object delete(@RequestParam String searchKeysId) { - searchKeysService.removeById(searchKeysId); + public Object delete(@RequestBody IdForms searchKeysIds) { + searchKeysService.removeByIds(searchKeysIds.getIds()); return ResponseData.success(); } @@ -73,7 +98,7 @@ */ @PostMapping(value = "/update") @ResponseBody - public Object update(SearchKeys searchKeys) { + public Object update(@RequestBody SearchKeys searchKeys) { searchKeysService.updateById(searchKeys); return ResponseData.success(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java new file mode 100644 index 0000000..c3d1185 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.system.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.system.model.ProductInfo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 商品信息 Mapper 接口 + *

+ * + * @author stylefeng123 + * @since 2022-05-05 + */ +public interface ProductInfoMapper extends BaseMapper { + + /** + * 产品数据检索 + * + * @return 产品价格列表 + */ + List searchDbProductPricePage(@Param("keywords") String keywords, @Param("page") Page page); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml new file mode 100644 index 0000000..99c83ba --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + id, max_price AS maxPrice, min_price AS minPrice, description + + + + '%' || #{keywords}|| '%' + + + CONCAT('%',#{keywords},'%') + + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml index 348f2a0..4f41b58 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml @@ -5,14 +5,14 @@ - + - id, keys, search_time AS searchTime, keep_days AS keepDays + id, keywords, search_time AS searchTime, keep_days AS keepDays diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java b/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java new file mode 100644 index 0000000..df0766c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java @@ -0,0 +1,38 @@ +package com.casic.missiles.modular.system.job; + +import cn.hutool.core.util.RandomUtil; +import com.casic.missiles.modular.system.service.IProductInfoService; +import lombok.SneakyThrows; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.math.BigDecimal; + +/** + * @ClassName QuartzJob + * @Description 依赖casic-job-quartz,并在CasicApplication上增加注解 @EnableScheduling + * @Author lwh + * @Date 2021/2/5 11:20 + * @Version 1.0 + */ +@Component +public class QuartzJob { + @Resource + private IProductInfoService productInfoService; + + /** + * + */ + @SneakyThrows + @Scheduled(cron = "0 0 10,14,16 * * ?") + public void execute() { + try { + Thread.sleep(RandomUtil.randomBigDecimal(new BigDecimal(2000)).intValue()); + System.out.println("-----Thread ID 每60秒执行一次"); + productInfoService.searchProducts(null); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java index 03190bf..d5c4ecd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java @@ -1,14 +1,74 @@ package com.casic.missiles.modular.system.model; +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import com.casic.missiles.core.base.json.DateDeserializer; import lombok.Data; +import java.util.Date; + /** - * 产品信息 + *

+ * 商品信息 + *

* - * @author lenovo + * @author stylefeng123 + * @since 2022-05-05 */ @Data -public class ProductInfo { - private String description; +@TableName("reptile_product_info") +public class ProductInfo extends Model { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + private Long id; + /** + * 页面价格 + */ + @TableField("price") private String price; + /** + * 满减价格 + */ + @TableField("actual_price") + private String actualPrice; + /** + * 优惠信息 + */ + @TableField("discount") + private String discount; + + /** + * 其他信息 + */ + private String description; + + + @TableField("key_id") + private Long keyId; + + /** + * 0 页面无效 1 价格偏高 + */ + private String flag; + @JSONField(serializeUsing = DateDeserializer.class) + @TableField("create_time") + private Date createTime; + @TableField(exist = false) + private String skuName; + @TableField(exist = false) + private String skuUrl; + + @Override + public String toString() { + return "ProductInfo{" + + "id=" + id + + ", description=" + description + + "}"; + } } diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 0e47785..0adbba2 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -37,9 +37,19 @@ com.casic + casic-job-quartz + ${extension.version} + + + com.casic casic-selenium-core ${extension.version} + + com.google.guava + guava + 30.1-jre + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java new file mode 100644 index 0000000..9dc3950 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java @@ -0,0 +1,94 @@ +package com.casic.missiles.modular.system.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.BaseController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.system.model.ProductInfo; +import com.casic.missiles.modular.system.service.IProductInfoService; +import com.casic.missiles.modular.system.service.ISearchKeysService; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 商品信息管理控制器 + * + * @author dev + * @Date 2022-05-05 15:46:28 + */ +@Controller +@RequestMapping("/productInfo") +public class ProductInfoController extends BaseController { + @Resource + private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + + /** + * 获取商品信息管理列表 + */ + @RequestMapping(value = "/list") + @ResponseBody + public Object list(String condition) { + return productInfoService.list(null); + } + + /** + * 获取商品信息管理分页列表 + */ + @RequestMapping(value = "/listPage") + @ResponseBody + public Object listPage(String condition) { + Page page = PageFactory.defaultPage(); + QueryWrapper query = new QueryWrapper<>(); + List productInfos = productInfoService.searchDbProductPricePage(condition, page); + page.setRecords(productInfos); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 新增商品信息管理 + */ + @RequestMapping(value = "/add") + @ResponseBody + public Object add(ProductInfo productInfo) { + productInfoService.save(productInfo); + return ResponseData.success(); + } + + /** + * 删除商品信息管理 + */ + @RequestMapping(value = "/delete") + @ResponseBody + public Object delete(@RequestParam String productInfoId) { + productInfoService.removeById(productInfoId); + return ResponseData.success(); + } + + /** + * 修改商品信息管理 + */ + @RequestMapping(value = "/update") + @ResponseBody + public Object update(ProductInfo productInfo) { + productInfoService.updateById(productInfo); + return ResponseData.success(); + } + + /** + * 商品信息管理详情 + */ + @RequestMapping(value = "/detail/{productInfoId}") + @ResponseBody + public Object detail(@PathVariable("productInfoId") String productInfoId) { + return ResponseData.success(productInfoService.getById(productInfoId)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java index 78c1892..446be24 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java @@ -1,11 +1,14 @@ package com.casic.missiles.modular.system.controller; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.BaseController; import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.form.IdForms; import com.casic.missiles.model.response.ResponseData; import com.casic.missiles.modular.system.model.SearchKeys; +import com.casic.missiles.modular.system.service.IProductInfoService; import com.casic.missiles.modular.system.service.ISearchKeysService; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; @@ -24,7 +27,25 @@ @Resource private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + /** + * 获取关键字管理列表 + */ + @GetMapping(value = "/loadSearch") + @ResponseBody + public Object loadSearch(String condition) { + new Thread(){ + @Override + public void run() { + super.run(); + productInfoService.searchProducts(null); + } + }.start(); + + return ResponseData.success(); + } /** * 获取关键字管理列表 @@ -43,6 +64,10 @@ public Object listPage(String condition) { Page page = PageFactory.defaultPage(); QueryWrapper query = new QueryWrapper<>(); + if (StrUtil.isNotEmpty(condition)) { + query.like("keywords", condition); + } + page = searchKeysService.page(page, query); return ResponseData.success(super.packForBT(page)); } @@ -52,7 +77,7 @@ */ @PostMapping(value = "/add") @ResponseBody - public Object add(SearchKeys searchKeys) { + public Object add(@RequestBody SearchKeys searchKeys) { searchKeysService.save(searchKeys); return ResponseData.success(); } @@ -62,8 +87,8 @@ */ @PostMapping(value = "/delete") @ResponseBody - public Object delete(@RequestParam String searchKeysId) { - searchKeysService.removeById(searchKeysId); + public Object delete(@RequestBody IdForms searchKeysIds) { + searchKeysService.removeByIds(searchKeysIds.getIds()); return ResponseData.success(); } @@ -73,7 +98,7 @@ */ @PostMapping(value = "/update") @ResponseBody - public Object update(SearchKeys searchKeys) { + public Object update(@RequestBody SearchKeys searchKeys) { searchKeysService.updateById(searchKeys); return ResponseData.success(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java new file mode 100644 index 0000000..c3d1185 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.system.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.system.model.ProductInfo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 商品信息 Mapper 接口 + *

+ * + * @author stylefeng123 + * @since 2022-05-05 + */ +public interface ProductInfoMapper extends BaseMapper { + + /** + * 产品数据检索 + * + * @return 产品价格列表 + */ + List searchDbProductPricePage(@Param("keywords") String keywords, @Param("page") Page page); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml new file mode 100644 index 0000000..99c83ba --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + id, max_price AS maxPrice, min_price AS minPrice, description + + + + '%' || #{keywords}|| '%' + + + CONCAT('%',#{keywords},'%') + + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml index 348f2a0..4f41b58 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml @@ -5,14 +5,14 @@ - + - id, keys, search_time AS searchTime, keep_days AS keepDays + id, keywords, search_time AS searchTime, keep_days AS keepDays diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java b/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java new file mode 100644 index 0000000..df0766c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java @@ -0,0 +1,38 @@ +package com.casic.missiles.modular.system.job; + +import cn.hutool.core.util.RandomUtil; +import com.casic.missiles.modular.system.service.IProductInfoService; +import lombok.SneakyThrows; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.math.BigDecimal; + +/** + * @ClassName QuartzJob + * @Description 依赖casic-job-quartz,并在CasicApplication上增加注解 @EnableScheduling + * @Author lwh + * @Date 2021/2/5 11:20 + * @Version 1.0 + */ +@Component +public class QuartzJob { + @Resource + private IProductInfoService productInfoService; + + /** + * + */ + @SneakyThrows + @Scheduled(cron = "0 0 10,14,16 * * ?") + public void execute() { + try { + Thread.sleep(RandomUtil.randomBigDecimal(new BigDecimal(2000)).intValue()); + System.out.println("-----Thread ID 每60秒执行一次"); + productInfoService.searchProducts(null); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java index 03190bf..d5c4ecd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java @@ -1,14 +1,74 @@ package com.casic.missiles.modular.system.model; +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import com.casic.missiles.core.base.json.DateDeserializer; import lombok.Data; +import java.util.Date; + /** - * 产品信息 + *

+ * 商品信息 + *

* - * @author lenovo + * @author stylefeng123 + * @since 2022-05-05 */ @Data -public class ProductInfo { - private String description; +@TableName("reptile_product_info") +public class ProductInfo extends Model { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + private Long id; + /** + * 页面价格 + */ + @TableField("price") private String price; + /** + * 满减价格 + */ + @TableField("actual_price") + private String actualPrice; + /** + * 优惠信息 + */ + @TableField("discount") + private String discount; + + /** + * 其他信息 + */ + private String description; + + + @TableField("key_id") + private Long keyId; + + /** + * 0 页面无效 1 价格偏高 + */ + private String flag; + @JSONField(serializeUsing = DateDeserializer.class) + @TableField("create_time") + private Date createTime; + @TableField(exist = false) + private String skuName; + @TableField(exist = false) + private String skuUrl; + + @Override + public String toString() { + return "ProductInfo{" + + "id=" + id + + ", description=" + description + + "}"; + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java index 09eb7ee..ed01581 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java @@ -1,8 +1,10 @@ package com.casic.missiles.modular.system.model; +import com.alibaba.fastjson.annotation.JSONField; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.extension.activerecord.Model; +import com.casic.missiles.core.base.json.DateDeserializer; import lombok.Data; import java.util.Date; @@ -26,12 +28,24 @@ */ private Long id; /** - * 检索关键字 + * 商品名称 */ - private String keys; + @TableField("sku_name") + private String skuName; + /** + * 商品url + */ + @TableField("sku_url") + private String skuUrl; + /** + * 设定价格 + */ + @TableField("price") + private String price; /** * 最后检索时间 */ + @JSONField(serializeUsing = DateDeserializer.class) @TableField("search_time") private Date searchTime; /** @@ -40,12 +54,10 @@ @TableField("keep_days") private Integer keepDays; - @Override public String toString() { return "SearchKeys{" + "id=" + id + - ", keys=" + keys + ", searchTime=" + searchTime + ", keepDays=" + keepDays + "}"; diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 0e47785..0adbba2 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -37,9 +37,19 @@ com.casic + casic-job-quartz + ${extension.version} + + + com.casic casic-selenium-core ${extension.version} + + com.google.guava + guava + 30.1-jre + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java new file mode 100644 index 0000000..9dc3950 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java @@ -0,0 +1,94 @@ +package com.casic.missiles.modular.system.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.BaseController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.system.model.ProductInfo; +import com.casic.missiles.modular.system.service.IProductInfoService; +import com.casic.missiles.modular.system.service.ISearchKeysService; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 商品信息管理控制器 + * + * @author dev + * @Date 2022-05-05 15:46:28 + */ +@Controller +@RequestMapping("/productInfo") +public class ProductInfoController extends BaseController { + @Resource + private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + + /** + * 获取商品信息管理列表 + */ + @RequestMapping(value = "/list") + @ResponseBody + public Object list(String condition) { + return productInfoService.list(null); + } + + /** + * 获取商品信息管理分页列表 + */ + @RequestMapping(value = "/listPage") + @ResponseBody + public Object listPage(String condition) { + Page page = PageFactory.defaultPage(); + QueryWrapper query = new QueryWrapper<>(); + List productInfos = productInfoService.searchDbProductPricePage(condition, page); + page.setRecords(productInfos); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 新增商品信息管理 + */ + @RequestMapping(value = "/add") + @ResponseBody + public Object add(ProductInfo productInfo) { + productInfoService.save(productInfo); + return ResponseData.success(); + } + + /** + * 删除商品信息管理 + */ + @RequestMapping(value = "/delete") + @ResponseBody + public Object delete(@RequestParam String productInfoId) { + productInfoService.removeById(productInfoId); + return ResponseData.success(); + } + + /** + * 修改商品信息管理 + */ + @RequestMapping(value = "/update") + @ResponseBody + public Object update(ProductInfo productInfo) { + productInfoService.updateById(productInfo); + return ResponseData.success(); + } + + /** + * 商品信息管理详情 + */ + @RequestMapping(value = "/detail/{productInfoId}") + @ResponseBody + public Object detail(@PathVariable("productInfoId") String productInfoId) { + return ResponseData.success(productInfoService.getById(productInfoId)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java index 78c1892..446be24 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java @@ -1,11 +1,14 @@ package com.casic.missiles.modular.system.controller; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.BaseController; import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.form.IdForms; import com.casic.missiles.model.response.ResponseData; import com.casic.missiles.modular.system.model.SearchKeys; +import com.casic.missiles.modular.system.service.IProductInfoService; import com.casic.missiles.modular.system.service.ISearchKeysService; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; @@ -24,7 +27,25 @@ @Resource private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + /** + * 获取关键字管理列表 + */ + @GetMapping(value = "/loadSearch") + @ResponseBody + public Object loadSearch(String condition) { + new Thread(){ + @Override + public void run() { + super.run(); + productInfoService.searchProducts(null); + } + }.start(); + + return ResponseData.success(); + } /** * 获取关键字管理列表 @@ -43,6 +64,10 @@ public Object listPage(String condition) { Page page = PageFactory.defaultPage(); QueryWrapper query = new QueryWrapper<>(); + if (StrUtil.isNotEmpty(condition)) { + query.like("keywords", condition); + } + page = searchKeysService.page(page, query); return ResponseData.success(super.packForBT(page)); } @@ -52,7 +77,7 @@ */ @PostMapping(value = "/add") @ResponseBody - public Object add(SearchKeys searchKeys) { + public Object add(@RequestBody SearchKeys searchKeys) { searchKeysService.save(searchKeys); return ResponseData.success(); } @@ -62,8 +87,8 @@ */ @PostMapping(value = "/delete") @ResponseBody - public Object delete(@RequestParam String searchKeysId) { - searchKeysService.removeById(searchKeysId); + public Object delete(@RequestBody IdForms searchKeysIds) { + searchKeysService.removeByIds(searchKeysIds.getIds()); return ResponseData.success(); } @@ -73,7 +98,7 @@ */ @PostMapping(value = "/update") @ResponseBody - public Object update(SearchKeys searchKeys) { + public Object update(@RequestBody SearchKeys searchKeys) { searchKeysService.updateById(searchKeys); return ResponseData.success(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java new file mode 100644 index 0000000..c3d1185 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.system.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.system.model.ProductInfo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 商品信息 Mapper 接口 + *

+ * + * @author stylefeng123 + * @since 2022-05-05 + */ +public interface ProductInfoMapper extends BaseMapper { + + /** + * 产品数据检索 + * + * @return 产品价格列表 + */ + List searchDbProductPricePage(@Param("keywords") String keywords, @Param("page") Page page); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml new file mode 100644 index 0000000..99c83ba --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + id, max_price AS maxPrice, min_price AS minPrice, description + + + + '%' || #{keywords}|| '%' + + + CONCAT('%',#{keywords},'%') + + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml index 348f2a0..4f41b58 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml @@ -5,14 +5,14 @@ - + - id, keys, search_time AS searchTime, keep_days AS keepDays + id, keywords, search_time AS searchTime, keep_days AS keepDays diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java b/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java new file mode 100644 index 0000000..df0766c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java @@ -0,0 +1,38 @@ +package com.casic.missiles.modular.system.job; + +import cn.hutool.core.util.RandomUtil; +import com.casic.missiles.modular.system.service.IProductInfoService; +import lombok.SneakyThrows; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.math.BigDecimal; + +/** + * @ClassName QuartzJob + * @Description 依赖casic-job-quartz,并在CasicApplication上增加注解 @EnableScheduling + * @Author lwh + * @Date 2021/2/5 11:20 + * @Version 1.0 + */ +@Component +public class QuartzJob { + @Resource + private IProductInfoService productInfoService; + + /** + * + */ + @SneakyThrows + @Scheduled(cron = "0 0 10,14,16 * * ?") + public void execute() { + try { + Thread.sleep(RandomUtil.randomBigDecimal(new BigDecimal(2000)).intValue()); + System.out.println("-----Thread ID 每60秒执行一次"); + productInfoService.searchProducts(null); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java index 03190bf..d5c4ecd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java @@ -1,14 +1,74 @@ package com.casic.missiles.modular.system.model; +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import com.casic.missiles.core.base.json.DateDeserializer; import lombok.Data; +import java.util.Date; + /** - * 产品信息 + *

+ * 商品信息 + *

* - * @author lenovo + * @author stylefeng123 + * @since 2022-05-05 */ @Data -public class ProductInfo { - private String description; +@TableName("reptile_product_info") +public class ProductInfo extends Model { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + private Long id; + /** + * 页面价格 + */ + @TableField("price") private String price; + /** + * 满减价格 + */ + @TableField("actual_price") + private String actualPrice; + /** + * 优惠信息 + */ + @TableField("discount") + private String discount; + + /** + * 其他信息 + */ + private String description; + + + @TableField("key_id") + private Long keyId; + + /** + * 0 页面无效 1 价格偏高 + */ + private String flag; + @JSONField(serializeUsing = DateDeserializer.class) + @TableField("create_time") + private Date createTime; + @TableField(exist = false) + private String skuName; + @TableField(exist = false) + private String skuUrl; + + @Override + public String toString() { + return "ProductInfo{" + + "id=" + id + + ", description=" + description + + "}"; + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java index 09eb7ee..ed01581 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java @@ -1,8 +1,10 @@ package com.casic.missiles.modular.system.model; +import com.alibaba.fastjson.annotation.JSONField; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.extension.activerecord.Model; +import com.casic.missiles.core.base.json.DateDeserializer; import lombok.Data; import java.util.Date; @@ -26,12 +28,24 @@ */ private Long id; /** - * 检索关键字 + * 商品名称 */ - private String keys; + @TableField("sku_name") + private String skuName; + /** + * 商品url + */ + @TableField("sku_url") + private String skuUrl; + /** + * 设定价格 + */ + @TableField("price") + private String price; /** * 最后检索时间 */ + @JSONField(serializeUsing = DateDeserializer.class) @TableField("search_time") private Date searchTime; /** @@ -40,12 +54,10 @@ @TableField("keep_days") private Integer keepDays; - @Override public String toString() { return "SearchKeys{" + "id=" + id + - ", keys=" + keys + ", searchTime=" + searchTime + ", keepDays=" + keepDays + "}"; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/service/IProductInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/system/service/IProductInfoService.java new file mode 100644 index 0000000..f6a8a35 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/service/IProductInfoService.java @@ -0,0 +1,30 @@ +package com.casic.missiles.modular.system.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.missiles.modular.system.model.ProductInfo; + +import java.util.List; + +/** + *

+ * 商品信息 服务类 + *

+ * + * @author stylefeng123 + * @since 2022-05-05 + */ +public interface IProductInfoService extends IService { + /** + * 检索商品接口定义 + * @param type jd tm + * @return + */ + public List searchProducts(String type); + /** + * 检索商品价格信息 + * @param type jd tm + * @return + */ + public List searchDbProductPricePage(String type, Page page); +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 0e47785..0adbba2 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -37,9 +37,19 @@ com.casic + casic-job-quartz + ${extension.version} + + + com.casic casic-selenium-core ${extension.version} + + com.google.guava + guava + 30.1-jre + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java new file mode 100644 index 0000000..9dc3950 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java @@ -0,0 +1,94 @@ +package com.casic.missiles.modular.system.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.BaseController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.system.model.ProductInfo; +import com.casic.missiles.modular.system.service.IProductInfoService; +import com.casic.missiles.modular.system.service.ISearchKeysService; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 商品信息管理控制器 + * + * @author dev + * @Date 2022-05-05 15:46:28 + */ +@Controller +@RequestMapping("/productInfo") +public class ProductInfoController extends BaseController { + @Resource + private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + + /** + * 获取商品信息管理列表 + */ + @RequestMapping(value = "/list") + @ResponseBody + public Object list(String condition) { + return productInfoService.list(null); + } + + /** + * 获取商品信息管理分页列表 + */ + @RequestMapping(value = "/listPage") + @ResponseBody + public Object listPage(String condition) { + Page page = PageFactory.defaultPage(); + QueryWrapper query = new QueryWrapper<>(); + List productInfos = productInfoService.searchDbProductPricePage(condition, page); + page.setRecords(productInfos); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 新增商品信息管理 + */ + @RequestMapping(value = "/add") + @ResponseBody + public Object add(ProductInfo productInfo) { + productInfoService.save(productInfo); + return ResponseData.success(); + } + + /** + * 删除商品信息管理 + */ + @RequestMapping(value = "/delete") + @ResponseBody + public Object delete(@RequestParam String productInfoId) { + productInfoService.removeById(productInfoId); + return ResponseData.success(); + } + + /** + * 修改商品信息管理 + */ + @RequestMapping(value = "/update") + @ResponseBody + public Object update(ProductInfo productInfo) { + productInfoService.updateById(productInfo); + return ResponseData.success(); + } + + /** + * 商品信息管理详情 + */ + @RequestMapping(value = "/detail/{productInfoId}") + @ResponseBody + public Object detail(@PathVariable("productInfoId") String productInfoId) { + return ResponseData.success(productInfoService.getById(productInfoId)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java index 78c1892..446be24 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java @@ -1,11 +1,14 @@ package com.casic.missiles.modular.system.controller; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.BaseController; import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.form.IdForms; import com.casic.missiles.model.response.ResponseData; import com.casic.missiles.modular.system.model.SearchKeys; +import com.casic.missiles.modular.system.service.IProductInfoService; import com.casic.missiles.modular.system.service.ISearchKeysService; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; @@ -24,7 +27,25 @@ @Resource private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + /** + * 获取关键字管理列表 + */ + @GetMapping(value = "/loadSearch") + @ResponseBody + public Object loadSearch(String condition) { + new Thread(){ + @Override + public void run() { + super.run(); + productInfoService.searchProducts(null); + } + }.start(); + + return ResponseData.success(); + } /** * 获取关键字管理列表 @@ -43,6 +64,10 @@ public Object listPage(String condition) { Page page = PageFactory.defaultPage(); QueryWrapper query = new QueryWrapper<>(); + if (StrUtil.isNotEmpty(condition)) { + query.like("keywords", condition); + } + page = searchKeysService.page(page, query); return ResponseData.success(super.packForBT(page)); } @@ -52,7 +77,7 @@ */ @PostMapping(value = "/add") @ResponseBody - public Object add(SearchKeys searchKeys) { + public Object add(@RequestBody SearchKeys searchKeys) { searchKeysService.save(searchKeys); return ResponseData.success(); } @@ -62,8 +87,8 @@ */ @PostMapping(value = "/delete") @ResponseBody - public Object delete(@RequestParam String searchKeysId) { - searchKeysService.removeById(searchKeysId); + public Object delete(@RequestBody IdForms searchKeysIds) { + searchKeysService.removeByIds(searchKeysIds.getIds()); return ResponseData.success(); } @@ -73,7 +98,7 @@ */ @PostMapping(value = "/update") @ResponseBody - public Object update(SearchKeys searchKeys) { + public Object update(@RequestBody SearchKeys searchKeys) { searchKeysService.updateById(searchKeys); return ResponseData.success(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java new file mode 100644 index 0000000..c3d1185 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.system.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.system.model.ProductInfo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 商品信息 Mapper 接口 + *

+ * + * @author stylefeng123 + * @since 2022-05-05 + */ +public interface ProductInfoMapper extends BaseMapper { + + /** + * 产品数据检索 + * + * @return 产品价格列表 + */ + List searchDbProductPricePage(@Param("keywords") String keywords, @Param("page") Page page); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml new file mode 100644 index 0000000..99c83ba --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + id, max_price AS maxPrice, min_price AS minPrice, description + + + + '%' || #{keywords}|| '%' + + + CONCAT('%',#{keywords},'%') + + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml index 348f2a0..4f41b58 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml @@ -5,14 +5,14 @@ - + - id, keys, search_time AS searchTime, keep_days AS keepDays + id, keywords, search_time AS searchTime, keep_days AS keepDays diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java b/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java new file mode 100644 index 0000000..df0766c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java @@ -0,0 +1,38 @@ +package com.casic.missiles.modular.system.job; + +import cn.hutool.core.util.RandomUtil; +import com.casic.missiles.modular.system.service.IProductInfoService; +import lombok.SneakyThrows; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.math.BigDecimal; + +/** + * @ClassName QuartzJob + * @Description 依赖casic-job-quartz,并在CasicApplication上增加注解 @EnableScheduling + * @Author lwh + * @Date 2021/2/5 11:20 + * @Version 1.0 + */ +@Component +public class QuartzJob { + @Resource + private IProductInfoService productInfoService; + + /** + * + */ + @SneakyThrows + @Scheduled(cron = "0 0 10,14,16 * * ?") + public void execute() { + try { + Thread.sleep(RandomUtil.randomBigDecimal(new BigDecimal(2000)).intValue()); + System.out.println("-----Thread ID 每60秒执行一次"); + productInfoService.searchProducts(null); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java index 03190bf..d5c4ecd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java @@ -1,14 +1,74 @@ package com.casic.missiles.modular.system.model; +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import com.casic.missiles.core.base.json.DateDeserializer; import lombok.Data; +import java.util.Date; + /** - * 产品信息 + *

+ * 商品信息 + *

* - * @author lenovo + * @author stylefeng123 + * @since 2022-05-05 */ @Data -public class ProductInfo { - private String description; +@TableName("reptile_product_info") +public class ProductInfo extends Model { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + private Long id; + /** + * 页面价格 + */ + @TableField("price") private String price; + /** + * 满减价格 + */ + @TableField("actual_price") + private String actualPrice; + /** + * 优惠信息 + */ + @TableField("discount") + private String discount; + + /** + * 其他信息 + */ + private String description; + + + @TableField("key_id") + private Long keyId; + + /** + * 0 页面无效 1 价格偏高 + */ + private String flag; + @JSONField(serializeUsing = DateDeserializer.class) + @TableField("create_time") + private Date createTime; + @TableField(exist = false) + private String skuName; + @TableField(exist = false) + private String skuUrl; + + @Override + public String toString() { + return "ProductInfo{" + + "id=" + id + + ", description=" + description + + "}"; + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java index 09eb7ee..ed01581 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java @@ -1,8 +1,10 @@ package com.casic.missiles.modular.system.model; +import com.alibaba.fastjson.annotation.JSONField; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.extension.activerecord.Model; +import com.casic.missiles.core.base.json.DateDeserializer; import lombok.Data; import java.util.Date; @@ -26,12 +28,24 @@ */ private Long id; /** - * 检索关键字 + * 商品名称 */ - private String keys; + @TableField("sku_name") + private String skuName; + /** + * 商品url + */ + @TableField("sku_url") + private String skuUrl; + /** + * 设定价格 + */ + @TableField("price") + private String price; /** * 最后检索时间 */ + @JSONField(serializeUsing = DateDeserializer.class) @TableField("search_time") private Date searchTime; /** @@ -40,12 +54,10 @@ @TableField("keep_days") private Integer keepDays; - @Override public String toString() { return "SearchKeys{" + "id=" + id + - ", keys=" + keys + ", searchTime=" + searchTime + ", keepDays=" + keepDays + "}"; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/service/IProductInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/system/service/IProductInfoService.java new file mode 100644 index 0000000..f6a8a35 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/service/IProductInfoService.java @@ -0,0 +1,30 @@ +package com.casic.missiles.modular.system.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.missiles.modular.system.model.ProductInfo; + +import java.util.List; + +/** + *

+ * 商品信息 服务类 + *

+ * + * @author stylefeng123 + * @since 2022-05-05 + */ +public interface IProductInfoService extends IService { + /** + * 检索商品接口定义 + * @param type jd tm + * @return + */ + public List searchProducts(String type); + /** + * 检索商品价格信息 + * @param type jd tm + * @return + */ + public List searchDbProductPricePage(String type, Page page); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductInfoServiceImpl.java new file mode 100644 index 0000000..e912cfd --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductInfoServiceImpl.java @@ -0,0 +1,218 @@ +package com.casic.missiles.modular.system.service.impl; + +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.modular.system.dao.ProductInfoMapper; +import com.casic.missiles.modular.system.model.ProductInfo; +import com.casic.missiles.modular.system.model.SearchKeys; +import com.casic.missiles.modular.system.service.IProductInfoService; +import com.casic.missiles.modular.system.service.ISearchKeysService; +import lombok.SneakyThrows; +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.chrome.ChromeDriver; +import org.openqa.selenium.chrome.ChromeOptions; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + *

+ * 商品信息 服务实现类 + *

+ * + * @author stylefeng123 + * @since 2022-05-05 + */ +@Service +public class ProductInfoServiceImpl extends ServiceImpl implements IProductInfoService { + @Value("${casic.webdriver.path}") + private String path; + @Value("${casic.tm.account}") + private String account; + @Value("${casic.tm.pwd}") + private String pwd; + @Resource + private ISearchKeysService searchKeysService; + + @Override + public List searchProducts(String type) { + System.setProperty("webdriver.chrome.driver", path); + List searchKeys = searchKeysService.list(); + Date searchTime = new Date(); + WebDriver webDriver = null; + try { + //驱动地址 + ChromeOptions option = new ChromeOptions(); + //去掉chrome 正受到自动测试软件的控制 + option.addArguments("disable-infobars"); + //开启开发者模式 + option.setExperimentalOption("excludeSwitches", Collections.singletonList("enable-automation")); + option.addArguments("--disable-blink-features"); + option.addArguments("--disable-blink-features=AutomationControlled"); + //初始化一个chrome浏览器实例 + webDriver = new ChromeDriver(option); + //最大化窗口 + webDriver.manage().window().maximize(); + //设置隐性等待时间 + webDriver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS); + for (SearchKeys searchKey : searchKeys) { +// List productInfos = searchJdProducts(webDriver, searchKey.getKeywords()); +// ProductInfo maxJd = productInfos.stream().max(Comparator.comparing(ProductInfo::getMaxPrice)).get(); +// ProductInfo minJd = productInfos.stream().min(Comparator.comparing(ProductInfo::getMaxPrice)).get(); +// // 过滤价格区间 +// ProductInfo info = new ProductInfo(); +// info.setKeyId(searchKey.getId()); +// info.setCreateTime(searchTime); +// info.setMaxPrice(maxJd.getMaxPrice()); +// info.setMinPrice(minJd.getMaxPrice()); +// StringBuilder jdStr = new StringBuilder(); +// jdStr.append("京东:").append(minJd.getDescription()).append("---").append(maxJd.getDescription()).append(" "); +// // 过滤天猫信息 +// List productTmInfos = searchTbProducts(webDriver, searchKey.getKeywords()); +// ProductInfo maxTb = productTmInfos.stream().max(Comparator.comparing(ProductInfo::getMaxPrice)).get(); +// ProductInfo minTb = productTmInfos.stream().min(Comparator.comparing(ProductInfo::getMaxPrice)).get(); +// info.setMaxTmPrice(maxTb.getMaxPrice()); +// info.setMinTmPrice(minTb.getMaxPrice()); +// jdStr.append("天猫:").append(minTb.getDescription()).append("---").append(maxTb.getDescription()).append(" "); + +// info.setDescription(jdStr.toString()); +// this.save(info); + searchKey.setSearchTime(searchTime); + searchKeysService.updateById(searchKey); + } + + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (webDriver != null) { + webDriver.close(); + webDriver.quit(); + } + } + return new ArrayList<>(); + } + + @Override + public List searchDbProductPricePage(String keywords, Page page) { + return this.baseMapper.searchDbProductPricePage(keywords, page); + } + + private ProductInfo searchJdDetail(WebDriver webDriver, String url) { + ProductInfo productInfo = new ProductInfo(); + //打开京东地址 + webDriver.get(url); + String title = webDriver.getTitle(); + WebElement skuEl = webDriver.findElement(By.className("sku-name")); + if (skuEl != null) { + String skuName = skuEl.getText(); + productInfo.setDescription(skuName); + } else { + productInfo.setFlag("1"); + } + + // NO1 读取价格信息 + WebElement priceEl = webDriver.findElement(By.className("p-price")); + if (priceEl != null) { + WebElement webP = priceEl.findElement(By.className("price")); + if (webP != null && NumberUtil.isNumber(webP.getText())) { + //设置页面价格 + productInfo.setPrice(webP.getText()); + } else { + //页面元素获取异常 判定为页面失效 + productInfo.setFlag("1"); + } + } else { + //页面元素获取异常 判定为页面失效 + productInfo.setFlag("1"); + } + + // NO2 读取打折信息 + WebElement promItem = webDriver.findElement(By.className("prom-item")); + if (promItem != null) { + //提取满减信息 + WebElement redElm = promItem.findElement(By.className("hl_red")); + String text = redElm.getText(); + if (StrUtil.isNotEmpty(text)) { + //提取满减 + String bg = promItem.findElement(By.className("hl_red_bg")).getText(); + String reg = "[\\u4E00-\\u9FA5]+"; + List list = Stream.of(reg.split(reg)).filter(StrUtil::isNotEmpty).collect(Collectors.toList()); + if (list.size() > 0 && list.stream().anyMatch(NumberUtil::isNumber)) { + //计算满减价格 + //判断价格是否符合满减数 + if ("满减".equals(bg) && list.size() > 2) { + BigDecimal skuPrice = NumberUtil.toBigDecimal(productInfo.getPrice()); + if (skuPrice.compareTo(NumberUtil.toBigDecimal(list.get(0))) >= 0) { + BigDecimal discountPrice = NumberUtil.toBigDecimal(list.get(1)); + //设置实际价格 + productInfo.setActualPrice(skuPrice.subtract(discountPrice).toString()); + } + } + } + } + } + + return productInfo; + } + + private List searchJdProducts(WebDriver webDriver, String keywords) { + //打开京东地址 + webDriver.get("https://search.jd.com/Search?keyword=" + keywords); + String title = webDriver.getTitle(); + List elementList = webDriver.findElements(By.className("gl-i-wrap")); + List productInfos = elementList.stream().map(webElement -> { + ProductInfo productInfo = new ProductInfo(); + productInfo.setDescription(webElement.findElement(By.className("p-name")).getText()); + String price = webElement.findElement(By.className("p-price")).getText(); + price = price.replaceAll("¥", ""); +// productInfo.setMaxPrice(price); + return productInfo; + }).collect(Collectors.toList()); + return productInfos; + } + + @SneakyThrows + private List searchTbProducts(WebDriver webDriver, String keyWords) { + //打开京东地址 + webDriver.get("https://login.taobao.com/member/login.jhtml?tpl_redirect_url=https%3A%2F%2Fwww.tmall.com&style=miniall&enup=true&newMini2=true&full_redirect=true&sub=true&from=tmall&allp=assets_css%3D3.0.10/login_pc.css&pms=1650640249767"); + Thread.sleep(10 * 1000L); + + // 预登录 + webDriver.findElement(By.xpath("//input[@name='fm-login-id']")).sendKeys(account); + webDriver.findElement(By.xpath("//input[@name='fm-login-password']")).sendKeys(pwd); + webDriver.findElement(By.xpath("//*[@class=\"fm-button fm-submit password-login\"]")).click(); + + String oldHandler = webDriver.getWindowHandle(); + webDriver.findElement(By.className("SearchInput--searchInputContent--1USWNEl")).sendKeys(keyWords); + Thread.sleep(10 * 1000L); + webDriver.findElement(By.className("SearchInput--searchButton--1Sz2UIn")).click(); + Thread.sleep(30 * 1000L); + // 获取当前handler + + Set sets = webDriver.getWindowHandles(); + String newWindow = sets.stream().filter(handler -> !oldHandler.equals(handler)).findFirst().get(); + webDriver.switchTo().window(newWindow); + + List tmElementList = webDriver.findElements(By.className("product-iWrap")); + List productInfos = tmElementList.stream().map(pElement -> { + ProductInfo productInfo = new ProductInfo(); + productInfo.setDescription(pElement.findElement(By.className("productTitle")).getText()); + String price = pElement.findElement(By.className("productPrice")).getText(); + System.out.println(price); + price = price.replaceAll("¥", ""); +// productInfo.setMaxPrice(price); + return productInfo; + }).collect(Collectors.toList()); + return productInfos; + } +} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 0e47785..0adbba2 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -37,9 +37,19 @@ com.casic + casic-job-quartz + ${extension.version} + + + com.casic casic-selenium-core ${extension.version} + + com.google.guava + guava + 30.1-jre + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java new file mode 100644 index 0000000..9dc3950 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java @@ -0,0 +1,94 @@ +package com.casic.missiles.modular.system.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.BaseController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.system.model.ProductInfo; +import com.casic.missiles.modular.system.service.IProductInfoService; +import com.casic.missiles.modular.system.service.ISearchKeysService; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 商品信息管理控制器 + * + * @author dev + * @Date 2022-05-05 15:46:28 + */ +@Controller +@RequestMapping("/productInfo") +public class ProductInfoController extends BaseController { + @Resource + private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + + /** + * 获取商品信息管理列表 + */ + @RequestMapping(value = "/list") + @ResponseBody + public Object list(String condition) { + return productInfoService.list(null); + } + + /** + * 获取商品信息管理分页列表 + */ + @RequestMapping(value = "/listPage") + @ResponseBody + public Object listPage(String condition) { + Page page = PageFactory.defaultPage(); + QueryWrapper query = new QueryWrapper<>(); + List productInfos = productInfoService.searchDbProductPricePage(condition, page); + page.setRecords(productInfos); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 新增商品信息管理 + */ + @RequestMapping(value = "/add") + @ResponseBody + public Object add(ProductInfo productInfo) { + productInfoService.save(productInfo); + return ResponseData.success(); + } + + /** + * 删除商品信息管理 + */ + @RequestMapping(value = "/delete") + @ResponseBody + public Object delete(@RequestParam String productInfoId) { + productInfoService.removeById(productInfoId); + return ResponseData.success(); + } + + /** + * 修改商品信息管理 + */ + @RequestMapping(value = "/update") + @ResponseBody + public Object update(ProductInfo productInfo) { + productInfoService.updateById(productInfo); + return ResponseData.success(); + } + + /** + * 商品信息管理详情 + */ + @RequestMapping(value = "/detail/{productInfoId}") + @ResponseBody + public Object detail(@PathVariable("productInfoId") String productInfoId) { + return ResponseData.success(productInfoService.getById(productInfoId)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java index 78c1892..446be24 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java @@ -1,11 +1,14 @@ package com.casic.missiles.modular.system.controller; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.BaseController; import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.form.IdForms; import com.casic.missiles.model.response.ResponseData; import com.casic.missiles.modular.system.model.SearchKeys; +import com.casic.missiles.modular.system.service.IProductInfoService; import com.casic.missiles.modular.system.service.ISearchKeysService; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; @@ -24,7 +27,25 @@ @Resource private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + /** + * 获取关键字管理列表 + */ + @GetMapping(value = "/loadSearch") + @ResponseBody + public Object loadSearch(String condition) { + new Thread(){ + @Override + public void run() { + super.run(); + productInfoService.searchProducts(null); + } + }.start(); + + return ResponseData.success(); + } /** * 获取关键字管理列表 @@ -43,6 +64,10 @@ public Object listPage(String condition) { Page page = PageFactory.defaultPage(); QueryWrapper query = new QueryWrapper<>(); + if (StrUtil.isNotEmpty(condition)) { + query.like("keywords", condition); + } + page = searchKeysService.page(page, query); return ResponseData.success(super.packForBT(page)); } @@ -52,7 +77,7 @@ */ @PostMapping(value = "/add") @ResponseBody - public Object add(SearchKeys searchKeys) { + public Object add(@RequestBody SearchKeys searchKeys) { searchKeysService.save(searchKeys); return ResponseData.success(); } @@ -62,8 +87,8 @@ */ @PostMapping(value = "/delete") @ResponseBody - public Object delete(@RequestParam String searchKeysId) { - searchKeysService.removeById(searchKeysId); + public Object delete(@RequestBody IdForms searchKeysIds) { + searchKeysService.removeByIds(searchKeysIds.getIds()); return ResponseData.success(); } @@ -73,7 +98,7 @@ */ @PostMapping(value = "/update") @ResponseBody - public Object update(SearchKeys searchKeys) { + public Object update(@RequestBody SearchKeys searchKeys) { searchKeysService.updateById(searchKeys); return ResponseData.success(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java new file mode 100644 index 0000000..c3d1185 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.system.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.system.model.ProductInfo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 商品信息 Mapper 接口 + *

+ * + * @author stylefeng123 + * @since 2022-05-05 + */ +public interface ProductInfoMapper extends BaseMapper { + + /** + * 产品数据检索 + * + * @return 产品价格列表 + */ + List searchDbProductPricePage(@Param("keywords") String keywords, @Param("page") Page page); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml new file mode 100644 index 0000000..99c83ba --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + id, max_price AS maxPrice, min_price AS minPrice, description + + + + '%' || #{keywords}|| '%' + + + CONCAT('%',#{keywords},'%') + + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml index 348f2a0..4f41b58 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml @@ -5,14 +5,14 @@ - + - id, keys, search_time AS searchTime, keep_days AS keepDays + id, keywords, search_time AS searchTime, keep_days AS keepDays diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java b/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java new file mode 100644 index 0000000..df0766c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java @@ -0,0 +1,38 @@ +package com.casic.missiles.modular.system.job; + +import cn.hutool.core.util.RandomUtil; +import com.casic.missiles.modular.system.service.IProductInfoService; +import lombok.SneakyThrows; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.math.BigDecimal; + +/** + * @ClassName QuartzJob + * @Description 依赖casic-job-quartz,并在CasicApplication上增加注解 @EnableScheduling + * @Author lwh + * @Date 2021/2/5 11:20 + * @Version 1.0 + */ +@Component +public class QuartzJob { + @Resource + private IProductInfoService productInfoService; + + /** + * + */ + @SneakyThrows + @Scheduled(cron = "0 0 10,14,16 * * ?") + public void execute() { + try { + Thread.sleep(RandomUtil.randomBigDecimal(new BigDecimal(2000)).intValue()); + System.out.println("-----Thread ID 每60秒执行一次"); + productInfoService.searchProducts(null); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java index 03190bf..d5c4ecd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java @@ -1,14 +1,74 @@ package com.casic.missiles.modular.system.model; +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import com.casic.missiles.core.base.json.DateDeserializer; import lombok.Data; +import java.util.Date; + /** - * 产品信息 + *

+ * 商品信息 + *

* - * @author lenovo + * @author stylefeng123 + * @since 2022-05-05 */ @Data -public class ProductInfo { - private String description; +@TableName("reptile_product_info") +public class ProductInfo extends Model { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + private Long id; + /** + * 页面价格 + */ + @TableField("price") private String price; + /** + * 满减价格 + */ + @TableField("actual_price") + private String actualPrice; + /** + * 优惠信息 + */ + @TableField("discount") + private String discount; + + /** + * 其他信息 + */ + private String description; + + + @TableField("key_id") + private Long keyId; + + /** + * 0 页面无效 1 价格偏高 + */ + private String flag; + @JSONField(serializeUsing = DateDeserializer.class) + @TableField("create_time") + private Date createTime; + @TableField(exist = false) + private String skuName; + @TableField(exist = false) + private String skuUrl; + + @Override + public String toString() { + return "ProductInfo{" + + "id=" + id + + ", description=" + description + + "}"; + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java index 09eb7ee..ed01581 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java @@ -1,8 +1,10 @@ package com.casic.missiles.modular.system.model; +import com.alibaba.fastjson.annotation.JSONField; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.extension.activerecord.Model; +import com.casic.missiles.core.base.json.DateDeserializer; import lombok.Data; import java.util.Date; @@ -26,12 +28,24 @@ */ private Long id; /** - * 检索关键字 + * 商品名称 */ - private String keys; + @TableField("sku_name") + private String skuName; + /** + * 商品url + */ + @TableField("sku_url") + private String skuUrl; + /** + * 设定价格 + */ + @TableField("price") + private String price; /** * 最后检索时间 */ + @JSONField(serializeUsing = DateDeserializer.class) @TableField("search_time") private Date searchTime; /** @@ -40,12 +54,10 @@ @TableField("keep_days") private Integer keepDays; - @Override public String toString() { return "SearchKeys{" + "id=" + id + - ", keys=" + keys + ", searchTime=" + searchTime + ", keepDays=" + keepDays + "}"; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/service/IProductInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/system/service/IProductInfoService.java new file mode 100644 index 0000000..f6a8a35 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/service/IProductInfoService.java @@ -0,0 +1,30 @@ +package com.casic.missiles.modular.system.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.missiles.modular.system.model.ProductInfo; + +import java.util.List; + +/** + *

+ * 商品信息 服务类 + *

+ * + * @author stylefeng123 + * @since 2022-05-05 + */ +public interface IProductInfoService extends IService { + /** + * 检索商品接口定义 + * @param type jd tm + * @return + */ + public List searchProducts(String type); + /** + * 检索商品价格信息 + * @param type jd tm + * @return + */ + public List searchDbProductPricePage(String type, Page page); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductInfoServiceImpl.java new file mode 100644 index 0000000..e912cfd --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductInfoServiceImpl.java @@ -0,0 +1,218 @@ +package com.casic.missiles.modular.system.service.impl; + +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.modular.system.dao.ProductInfoMapper; +import com.casic.missiles.modular.system.model.ProductInfo; +import com.casic.missiles.modular.system.model.SearchKeys; +import com.casic.missiles.modular.system.service.IProductInfoService; +import com.casic.missiles.modular.system.service.ISearchKeysService; +import lombok.SneakyThrows; +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.chrome.ChromeDriver; +import org.openqa.selenium.chrome.ChromeOptions; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + *

+ * 商品信息 服务实现类 + *

+ * + * @author stylefeng123 + * @since 2022-05-05 + */ +@Service +public class ProductInfoServiceImpl extends ServiceImpl implements IProductInfoService { + @Value("${casic.webdriver.path}") + private String path; + @Value("${casic.tm.account}") + private String account; + @Value("${casic.tm.pwd}") + private String pwd; + @Resource + private ISearchKeysService searchKeysService; + + @Override + public List searchProducts(String type) { + System.setProperty("webdriver.chrome.driver", path); + List searchKeys = searchKeysService.list(); + Date searchTime = new Date(); + WebDriver webDriver = null; + try { + //驱动地址 + ChromeOptions option = new ChromeOptions(); + //去掉chrome 正受到自动测试软件的控制 + option.addArguments("disable-infobars"); + //开启开发者模式 + option.setExperimentalOption("excludeSwitches", Collections.singletonList("enable-automation")); + option.addArguments("--disable-blink-features"); + option.addArguments("--disable-blink-features=AutomationControlled"); + //初始化一个chrome浏览器实例 + webDriver = new ChromeDriver(option); + //最大化窗口 + webDriver.manage().window().maximize(); + //设置隐性等待时间 + webDriver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS); + for (SearchKeys searchKey : searchKeys) { +// List productInfos = searchJdProducts(webDriver, searchKey.getKeywords()); +// ProductInfo maxJd = productInfos.stream().max(Comparator.comparing(ProductInfo::getMaxPrice)).get(); +// ProductInfo minJd = productInfos.stream().min(Comparator.comparing(ProductInfo::getMaxPrice)).get(); +// // 过滤价格区间 +// ProductInfo info = new ProductInfo(); +// info.setKeyId(searchKey.getId()); +// info.setCreateTime(searchTime); +// info.setMaxPrice(maxJd.getMaxPrice()); +// info.setMinPrice(minJd.getMaxPrice()); +// StringBuilder jdStr = new StringBuilder(); +// jdStr.append("京东:").append(minJd.getDescription()).append("---").append(maxJd.getDescription()).append(" "); +// // 过滤天猫信息 +// List productTmInfos = searchTbProducts(webDriver, searchKey.getKeywords()); +// ProductInfo maxTb = productTmInfos.stream().max(Comparator.comparing(ProductInfo::getMaxPrice)).get(); +// ProductInfo minTb = productTmInfos.stream().min(Comparator.comparing(ProductInfo::getMaxPrice)).get(); +// info.setMaxTmPrice(maxTb.getMaxPrice()); +// info.setMinTmPrice(minTb.getMaxPrice()); +// jdStr.append("天猫:").append(minTb.getDescription()).append("---").append(maxTb.getDescription()).append(" "); + +// info.setDescription(jdStr.toString()); +// this.save(info); + searchKey.setSearchTime(searchTime); + searchKeysService.updateById(searchKey); + } + + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (webDriver != null) { + webDriver.close(); + webDriver.quit(); + } + } + return new ArrayList<>(); + } + + @Override + public List searchDbProductPricePage(String keywords, Page page) { + return this.baseMapper.searchDbProductPricePage(keywords, page); + } + + private ProductInfo searchJdDetail(WebDriver webDriver, String url) { + ProductInfo productInfo = new ProductInfo(); + //打开京东地址 + webDriver.get(url); + String title = webDriver.getTitle(); + WebElement skuEl = webDriver.findElement(By.className("sku-name")); + if (skuEl != null) { + String skuName = skuEl.getText(); + productInfo.setDescription(skuName); + } else { + productInfo.setFlag("1"); + } + + // NO1 读取价格信息 + WebElement priceEl = webDriver.findElement(By.className("p-price")); + if (priceEl != null) { + WebElement webP = priceEl.findElement(By.className("price")); + if (webP != null && NumberUtil.isNumber(webP.getText())) { + //设置页面价格 + productInfo.setPrice(webP.getText()); + } else { + //页面元素获取异常 判定为页面失效 + productInfo.setFlag("1"); + } + } else { + //页面元素获取异常 判定为页面失效 + productInfo.setFlag("1"); + } + + // NO2 读取打折信息 + WebElement promItem = webDriver.findElement(By.className("prom-item")); + if (promItem != null) { + //提取满减信息 + WebElement redElm = promItem.findElement(By.className("hl_red")); + String text = redElm.getText(); + if (StrUtil.isNotEmpty(text)) { + //提取满减 + String bg = promItem.findElement(By.className("hl_red_bg")).getText(); + String reg = "[\\u4E00-\\u9FA5]+"; + List list = Stream.of(reg.split(reg)).filter(StrUtil::isNotEmpty).collect(Collectors.toList()); + if (list.size() > 0 && list.stream().anyMatch(NumberUtil::isNumber)) { + //计算满减价格 + //判断价格是否符合满减数 + if ("满减".equals(bg) && list.size() > 2) { + BigDecimal skuPrice = NumberUtil.toBigDecimal(productInfo.getPrice()); + if (skuPrice.compareTo(NumberUtil.toBigDecimal(list.get(0))) >= 0) { + BigDecimal discountPrice = NumberUtil.toBigDecimal(list.get(1)); + //设置实际价格 + productInfo.setActualPrice(skuPrice.subtract(discountPrice).toString()); + } + } + } + } + } + + return productInfo; + } + + private List searchJdProducts(WebDriver webDriver, String keywords) { + //打开京东地址 + webDriver.get("https://search.jd.com/Search?keyword=" + keywords); + String title = webDriver.getTitle(); + List elementList = webDriver.findElements(By.className("gl-i-wrap")); + List productInfos = elementList.stream().map(webElement -> { + ProductInfo productInfo = new ProductInfo(); + productInfo.setDescription(webElement.findElement(By.className("p-name")).getText()); + String price = webElement.findElement(By.className("p-price")).getText(); + price = price.replaceAll("¥", ""); +// productInfo.setMaxPrice(price); + return productInfo; + }).collect(Collectors.toList()); + return productInfos; + } + + @SneakyThrows + private List searchTbProducts(WebDriver webDriver, String keyWords) { + //打开京东地址 + webDriver.get("https://login.taobao.com/member/login.jhtml?tpl_redirect_url=https%3A%2F%2Fwww.tmall.com&style=miniall&enup=true&newMini2=true&full_redirect=true&sub=true&from=tmall&allp=assets_css%3D3.0.10/login_pc.css&pms=1650640249767"); + Thread.sleep(10 * 1000L); + + // 预登录 + webDriver.findElement(By.xpath("//input[@name='fm-login-id']")).sendKeys(account); + webDriver.findElement(By.xpath("//input[@name='fm-login-password']")).sendKeys(pwd); + webDriver.findElement(By.xpath("//*[@class=\"fm-button fm-submit password-login\"]")).click(); + + String oldHandler = webDriver.getWindowHandle(); + webDriver.findElement(By.className("SearchInput--searchInputContent--1USWNEl")).sendKeys(keyWords); + Thread.sleep(10 * 1000L); + webDriver.findElement(By.className("SearchInput--searchButton--1Sz2UIn")).click(); + Thread.sleep(30 * 1000L); + // 获取当前handler + + Set sets = webDriver.getWindowHandles(); + String newWindow = sets.stream().filter(handler -> !oldHandler.equals(handler)).findFirst().get(); + webDriver.switchTo().window(newWindow); + + List tmElementList = webDriver.findElements(By.className("product-iWrap")); + List productInfos = tmElementList.stream().map(pElement -> { + ProductInfo productInfo = new ProductInfo(); + productInfo.setDescription(pElement.findElement(By.className("productTitle")).getText()); + String price = pElement.findElement(By.className("productPrice")).getText(); + System.out.println(price); + price = price.replaceAll("¥", ""); +// productInfo.setMaxPrice(price); + return productInfo; + }).collect(Collectors.toList()); + return productInfos; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductServiceImpl.java deleted file mode 100644 index 4e72150..0000000 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductServiceImpl.java +++ /dev/null @@ -1,144 +0,0 @@ -package com.casic.missiles.modular.system.service.impl; - -import com.casic.missiles.modular.system.model.ProductInfo; -import com.casic.missiles.modular.system.service.IProductSearchService; -import lombok.SneakyThrows; -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.chrome.ChromeOptions; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; - -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -/** - * 产品搜索实例 - * - * @author lwh - */ -@Component -public class ProductServiceImpl implements IProductSearchService { - @Value("${casic.webdriver.path}") - private String path; - @Override - public List searchProducts(String type) { - //驱动地址 - String chromedriver = "D:\\dev-soft\\seleuim-chmod\\chromedriver.exe"; - System.setProperty("webdriver.chrome.driver", path); - ChromeOptions option = new ChromeOptions(); - //去掉chrome 正受到自动测试软件的控制 - option.addArguments("disable-infobars"); - //开启开发者模式 - option.setExperimentalOption("excludeSwitches", Collections.singletonList("enable-automation")); - option.addArguments("--disable-blink-features"); - option.addArguments("--disable-blink-features=AutomationControlled"); - //初始化一个chrome浏览器实例 - WebDriver webDriver = new ChromeDriver(option); - //最大化窗口 - webDriver.manage().window().maximize(); - //设置隐性等待时间 - webDriver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS); - - return searchJdProducts(webDriver); - } - - private List searchJdProducts(WebDriver webDriver) { - //打开京东地址 - webDriver.get("https://search.jd.com/Search?keyword=%E8%8B%B9%E6%9E%9C13"); - String title = webDriver.getTitle(); - List elementList = webDriver.findElements(By.className("gl-i-wrap")); - List productInfos = elementList.stream().map(webElement -> { - ProductInfo productInfo = new ProductInfo(); - productInfo.setDescription(webElement.findElement(By.className("p-name")).getText()); - productInfo.setPrice(webElement.findElement(By.className("p-price")).getText()); - return productInfo; - }).collect(Collectors.toList()); - return productInfos; - } - - @SneakyThrows - private List searchTbProducts(WebDriver webDriver) { - //打开京东地址 - webDriver.get("https://login.taobao.com/member/login.jhtml?tpl_redirect_url=https%3A%2F%2Fwww.tmall.com&style=miniall&enup=true&newMini2=true&full_redirect=true&sub=true&from=tmall&allp=assets_css%3D3.0.10/login_pc.css&pms=1650640249767"); - Thread.sleep(10 * 1000L); - - // 预登录 - webDriver.findElement(By.xpath("//input[@name='fm-login-id']")).sendKeys("18600202639"); - webDriver.findElement(By.xpath("//input[@name='fm-login-password']")).sendKeys("19881126yu"); - webDriver.findElement(By.xpath("//*[@class=\"fm-button fm-submit password-login\"]")).click(); - - String oldHandler = webDriver.getWindowHandle(); - webDriver.findElement(By.className("SearchInput--searchInputContent--1USWNEl")).sendKeys("苹果13"); - Thread.sleep(10 * 1000L); - webDriver.findElement(By.className("SearchInput--searchButton--1Sz2UIn")).click(); - Thread.sleep(30 * 1000L); - // 获取当前handler - - Set sets = webDriver.getWindowHandles(); - String newWindow = sets.stream().filter(handler -> !oldHandler.equals(handler)).findFirst().get(); - webDriver.switchTo().window(newWindow); - - List tmElementList = webDriver.findElements(By.className("product-iWrap")); - List productInfos = tmElementList.stream().map(pElement -> { - ProductInfo productInfo = new ProductInfo(); - productInfo.setDescription(pElement.findElement(By.className("productPrice")).getText()); - productInfo.setPrice(pElement.findElement(By.className("productTitle")).getText()); - return productInfo; - }).collect(Collectors.toList()); - return productInfos; - } - - public static void main(String[] args) throws InterruptedException { - //驱动地址 - String chromedriver = "D:\\dev-soft\\seleuim-chmod\\chromedriver.exe"; - System.setProperty("webdriver.chrome.driver", chromedriver); - ChromeOptions option = new ChromeOptions(); - //去掉chrome 正受到自动测试软件的控制 - option.addArguments("disable-infobars"); - //开启开发者模式 - option.setExperimentalOption("excludeSwitches", Collections.singletonList("enable-automation")); - option.addArguments("--disable-blink-features"); - option.addArguments("--disable-blink-features=AutomationControlled"); - //初始化一个chrome浏览器实例 - WebDriver webDriver = new ChromeDriver(option); - //最大化窗口 - webDriver.manage().window().maximize(); - //设置隐性等待时间 - webDriver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS); - //打开京东地址 - webDriver.get("https://login.taobao.com/member/login.jhtml?tpl_redirect_url=https%3A%2F%2Fwww.tmall.com&style=miniall&enup=true&newMini2=true&full_redirect=true&sub=true&from=tmall&allp=assets_css%3D3.0.10/login_pc.css&pms=1650640249767"); - Thread.sleep(10 * 1000L); - - // 预登录 - webDriver.findElement(By.xpath("//input[@name='fm-login-id']")).sendKeys("18600202639"); - webDriver.findElement(By.xpath("//input[@name='fm-login-password']")).sendKeys("19881126yu"); - webDriver.findElement(By.xpath("//*[@class=\"fm-button fm-submit password-login\"]")).click(); - - String oldHandler = webDriver.getWindowHandle(); - webDriver.findElement(By.className("SearchInput--searchInputContent--1USWNEl")).sendKeys("苹果13"); - Thread.sleep(10 * 1000L); - webDriver.findElement(By.className("SearchInput--searchButton--1Sz2UIn")).click(); - Thread.sleep(30 * 1000L); - // 获取当前handler - - Set sets = webDriver.getWindowHandles(); - String newWindow = sets.stream().filter(handler -> !oldHandler.equals(handler)).findFirst().get(); - webDriver.switchTo().window(newWindow); - - List tmElementList = webDriver.findElements(By.className("product-iWrap")); - List productInfos = tmElementList.stream().map(pElement -> { - ProductInfo productInfo = new ProductInfo(); - productInfo.setDescription(pElement.findElement(By.className("productPrice")).getText()); - productInfo.setPrice(pElement.findElement(By.className("productTitle")).getText()); - return productInfo; - }).collect(Collectors.toList()); - - System.out.println(productInfos); - } -} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 0e47785..0adbba2 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -37,9 +37,19 @@ com.casic + casic-job-quartz + ${extension.version} + + + com.casic casic-selenium-core ${extension.version} + + com.google.guava + guava + 30.1-jre + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java new file mode 100644 index 0000000..9dc3950 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java @@ -0,0 +1,94 @@ +package com.casic.missiles.modular.system.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.BaseController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.system.model.ProductInfo; +import com.casic.missiles.modular.system.service.IProductInfoService; +import com.casic.missiles.modular.system.service.ISearchKeysService; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 商品信息管理控制器 + * + * @author dev + * @Date 2022-05-05 15:46:28 + */ +@Controller +@RequestMapping("/productInfo") +public class ProductInfoController extends BaseController { + @Resource + private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + + /** + * 获取商品信息管理列表 + */ + @RequestMapping(value = "/list") + @ResponseBody + public Object list(String condition) { + return productInfoService.list(null); + } + + /** + * 获取商品信息管理分页列表 + */ + @RequestMapping(value = "/listPage") + @ResponseBody + public Object listPage(String condition) { + Page page = PageFactory.defaultPage(); + QueryWrapper query = new QueryWrapper<>(); + List productInfos = productInfoService.searchDbProductPricePage(condition, page); + page.setRecords(productInfos); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 新增商品信息管理 + */ + @RequestMapping(value = "/add") + @ResponseBody + public Object add(ProductInfo productInfo) { + productInfoService.save(productInfo); + return ResponseData.success(); + } + + /** + * 删除商品信息管理 + */ + @RequestMapping(value = "/delete") + @ResponseBody + public Object delete(@RequestParam String productInfoId) { + productInfoService.removeById(productInfoId); + return ResponseData.success(); + } + + /** + * 修改商品信息管理 + */ + @RequestMapping(value = "/update") + @ResponseBody + public Object update(ProductInfo productInfo) { + productInfoService.updateById(productInfo); + return ResponseData.success(); + } + + /** + * 商品信息管理详情 + */ + @RequestMapping(value = "/detail/{productInfoId}") + @ResponseBody + public Object detail(@PathVariable("productInfoId") String productInfoId) { + return ResponseData.success(productInfoService.getById(productInfoId)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java index 78c1892..446be24 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java @@ -1,11 +1,14 @@ package com.casic.missiles.modular.system.controller; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.BaseController; import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.form.IdForms; import com.casic.missiles.model.response.ResponseData; import com.casic.missiles.modular.system.model.SearchKeys; +import com.casic.missiles.modular.system.service.IProductInfoService; import com.casic.missiles.modular.system.service.ISearchKeysService; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; @@ -24,7 +27,25 @@ @Resource private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + /** + * 获取关键字管理列表 + */ + @GetMapping(value = "/loadSearch") + @ResponseBody + public Object loadSearch(String condition) { + new Thread(){ + @Override + public void run() { + super.run(); + productInfoService.searchProducts(null); + } + }.start(); + + return ResponseData.success(); + } /** * 获取关键字管理列表 @@ -43,6 +64,10 @@ public Object listPage(String condition) { Page page = PageFactory.defaultPage(); QueryWrapper query = new QueryWrapper<>(); + if (StrUtil.isNotEmpty(condition)) { + query.like("keywords", condition); + } + page = searchKeysService.page(page, query); return ResponseData.success(super.packForBT(page)); } @@ -52,7 +77,7 @@ */ @PostMapping(value = "/add") @ResponseBody - public Object add(SearchKeys searchKeys) { + public Object add(@RequestBody SearchKeys searchKeys) { searchKeysService.save(searchKeys); return ResponseData.success(); } @@ -62,8 +87,8 @@ */ @PostMapping(value = "/delete") @ResponseBody - public Object delete(@RequestParam String searchKeysId) { - searchKeysService.removeById(searchKeysId); + public Object delete(@RequestBody IdForms searchKeysIds) { + searchKeysService.removeByIds(searchKeysIds.getIds()); return ResponseData.success(); } @@ -73,7 +98,7 @@ */ @PostMapping(value = "/update") @ResponseBody - public Object update(SearchKeys searchKeys) { + public Object update(@RequestBody SearchKeys searchKeys) { searchKeysService.updateById(searchKeys); return ResponseData.success(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java new file mode 100644 index 0000000..c3d1185 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.system.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.system.model.ProductInfo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 商品信息 Mapper 接口 + *

+ * + * @author stylefeng123 + * @since 2022-05-05 + */ +public interface ProductInfoMapper extends BaseMapper { + + /** + * 产品数据检索 + * + * @return 产品价格列表 + */ + List searchDbProductPricePage(@Param("keywords") String keywords, @Param("page") Page page); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml new file mode 100644 index 0000000..99c83ba --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + id, max_price AS maxPrice, min_price AS minPrice, description + + + + '%' || #{keywords}|| '%' + + + CONCAT('%',#{keywords},'%') + + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml index 348f2a0..4f41b58 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml @@ -5,14 +5,14 @@ - + - id, keys, search_time AS searchTime, keep_days AS keepDays + id, keywords, search_time AS searchTime, keep_days AS keepDays diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java b/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java new file mode 100644 index 0000000..df0766c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java @@ -0,0 +1,38 @@ +package com.casic.missiles.modular.system.job; + +import cn.hutool.core.util.RandomUtil; +import com.casic.missiles.modular.system.service.IProductInfoService; +import lombok.SneakyThrows; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.math.BigDecimal; + +/** + * @ClassName QuartzJob + * @Description 依赖casic-job-quartz,并在CasicApplication上增加注解 @EnableScheduling + * @Author lwh + * @Date 2021/2/5 11:20 + * @Version 1.0 + */ +@Component +public class QuartzJob { + @Resource + private IProductInfoService productInfoService; + + /** + * + */ + @SneakyThrows + @Scheduled(cron = "0 0 10,14,16 * * ?") + public void execute() { + try { + Thread.sleep(RandomUtil.randomBigDecimal(new BigDecimal(2000)).intValue()); + System.out.println("-----Thread ID 每60秒执行一次"); + productInfoService.searchProducts(null); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java index 03190bf..d5c4ecd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java @@ -1,14 +1,74 @@ package com.casic.missiles.modular.system.model; +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import com.casic.missiles.core.base.json.DateDeserializer; import lombok.Data; +import java.util.Date; + /** - * 产品信息 + *

+ * 商品信息 + *

* - * @author lenovo + * @author stylefeng123 + * @since 2022-05-05 */ @Data -public class ProductInfo { - private String description; +@TableName("reptile_product_info") +public class ProductInfo extends Model { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + private Long id; + /** + * 页面价格 + */ + @TableField("price") private String price; + /** + * 满减价格 + */ + @TableField("actual_price") + private String actualPrice; + /** + * 优惠信息 + */ + @TableField("discount") + private String discount; + + /** + * 其他信息 + */ + private String description; + + + @TableField("key_id") + private Long keyId; + + /** + * 0 页面无效 1 价格偏高 + */ + private String flag; + @JSONField(serializeUsing = DateDeserializer.class) + @TableField("create_time") + private Date createTime; + @TableField(exist = false) + private String skuName; + @TableField(exist = false) + private String skuUrl; + + @Override + public String toString() { + return "ProductInfo{" + + "id=" + id + + ", description=" + description + + "}"; + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java index 09eb7ee..ed01581 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java @@ -1,8 +1,10 @@ package com.casic.missiles.modular.system.model; +import com.alibaba.fastjson.annotation.JSONField; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.extension.activerecord.Model; +import com.casic.missiles.core.base.json.DateDeserializer; import lombok.Data; import java.util.Date; @@ -26,12 +28,24 @@ */ private Long id; /** - * 检索关键字 + * 商品名称 */ - private String keys; + @TableField("sku_name") + private String skuName; + /** + * 商品url + */ + @TableField("sku_url") + private String skuUrl; + /** + * 设定价格 + */ + @TableField("price") + private String price; /** * 最后检索时间 */ + @JSONField(serializeUsing = DateDeserializer.class) @TableField("search_time") private Date searchTime; /** @@ -40,12 +54,10 @@ @TableField("keep_days") private Integer keepDays; - @Override public String toString() { return "SearchKeys{" + "id=" + id + - ", keys=" + keys + ", searchTime=" + searchTime + ", keepDays=" + keepDays + "}"; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/service/IProductInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/system/service/IProductInfoService.java new file mode 100644 index 0000000..f6a8a35 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/service/IProductInfoService.java @@ -0,0 +1,30 @@ +package com.casic.missiles.modular.system.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.missiles.modular.system.model.ProductInfo; + +import java.util.List; + +/** + *

+ * 商品信息 服务类 + *

+ * + * @author stylefeng123 + * @since 2022-05-05 + */ +public interface IProductInfoService extends IService { + /** + * 检索商品接口定义 + * @param type jd tm + * @return + */ + public List searchProducts(String type); + /** + * 检索商品价格信息 + * @param type jd tm + * @return + */ + public List searchDbProductPricePage(String type, Page page); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductInfoServiceImpl.java new file mode 100644 index 0000000..e912cfd --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductInfoServiceImpl.java @@ -0,0 +1,218 @@ +package com.casic.missiles.modular.system.service.impl; + +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.modular.system.dao.ProductInfoMapper; +import com.casic.missiles.modular.system.model.ProductInfo; +import com.casic.missiles.modular.system.model.SearchKeys; +import com.casic.missiles.modular.system.service.IProductInfoService; +import com.casic.missiles.modular.system.service.ISearchKeysService; +import lombok.SneakyThrows; +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.chrome.ChromeDriver; +import org.openqa.selenium.chrome.ChromeOptions; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + *

+ * 商品信息 服务实现类 + *

+ * + * @author stylefeng123 + * @since 2022-05-05 + */ +@Service +public class ProductInfoServiceImpl extends ServiceImpl implements IProductInfoService { + @Value("${casic.webdriver.path}") + private String path; + @Value("${casic.tm.account}") + private String account; + @Value("${casic.tm.pwd}") + private String pwd; + @Resource + private ISearchKeysService searchKeysService; + + @Override + public List searchProducts(String type) { + System.setProperty("webdriver.chrome.driver", path); + List searchKeys = searchKeysService.list(); + Date searchTime = new Date(); + WebDriver webDriver = null; + try { + //驱动地址 + ChromeOptions option = new ChromeOptions(); + //去掉chrome 正受到自动测试软件的控制 + option.addArguments("disable-infobars"); + //开启开发者模式 + option.setExperimentalOption("excludeSwitches", Collections.singletonList("enable-automation")); + option.addArguments("--disable-blink-features"); + option.addArguments("--disable-blink-features=AutomationControlled"); + //初始化一个chrome浏览器实例 + webDriver = new ChromeDriver(option); + //最大化窗口 + webDriver.manage().window().maximize(); + //设置隐性等待时间 + webDriver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS); + for (SearchKeys searchKey : searchKeys) { +// List productInfos = searchJdProducts(webDriver, searchKey.getKeywords()); +// ProductInfo maxJd = productInfos.stream().max(Comparator.comparing(ProductInfo::getMaxPrice)).get(); +// ProductInfo minJd = productInfos.stream().min(Comparator.comparing(ProductInfo::getMaxPrice)).get(); +// // 过滤价格区间 +// ProductInfo info = new ProductInfo(); +// info.setKeyId(searchKey.getId()); +// info.setCreateTime(searchTime); +// info.setMaxPrice(maxJd.getMaxPrice()); +// info.setMinPrice(minJd.getMaxPrice()); +// StringBuilder jdStr = new StringBuilder(); +// jdStr.append("京东:").append(minJd.getDescription()).append("---").append(maxJd.getDescription()).append(" "); +// // 过滤天猫信息 +// List productTmInfos = searchTbProducts(webDriver, searchKey.getKeywords()); +// ProductInfo maxTb = productTmInfos.stream().max(Comparator.comparing(ProductInfo::getMaxPrice)).get(); +// ProductInfo minTb = productTmInfos.stream().min(Comparator.comparing(ProductInfo::getMaxPrice)).get(); +// info.setMaxTmPrice(maxTb.getMaxPrice()); +// info.setMinTmPrice(minTb.getMaxPrice()); +// jdStr.append("天猫:").append(minTb.getDescription()).append("---").append(maxTb.getDescription()).append(" "); + +// info.setDescription(jdStr.toString()); +// this.save(info); + searchKey.setSearchTime(searchTime); + searchKeysService.updateById(searchKey); + } + + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (webDriver != null) { + webDriver.close(); + webDriver.quit(); + } + } + return new ArrayList<>(); + } + + @Override + public List searchDbProductPricePage(String keywords, Page page) { + return this.baseMapper.searchDbProductPricePage(keywords, page); + } + + private ProductInfo searchJdDetail(WebDriver webDriver, String url) { + ProductInfo productInfo = new ProductInfo(); + //打开京东地址 + webDriver.get(url); + String title = webDriver.getTitle(); + WebElement skuEl = webDriver.findElement(By.className("sku-name")); + if (skuEl != null) { + String skuName = skuEl.getText(); + productInfo.setDescription(skuName); + } else { + productInfo.setFlag("1"); + } + + // NO1 读取价格信息 + WebElement priceEl = webDriver.findElement(By.className("p-price")); + if (priceEl != null) { + WebElement webP = priceEl.findElement(By.className("price")); + if (webP != null && NumberUtil.isNumber(webP.getText())) { + //设置页面价格 + productInfo.setPrice(webP.getText()); + } else { + //页面元素获取异常 判定为页面失效 + productInfo.setFlag("1"); + } + } else { + //页面元素获取异常 判定为页面失效 + productInfo.setFlag("1"); + } + + // NO2 读取打折信息 + WebElement promItem = webDriver.findElement(By.className("prom-item")); + if (promItem != null) { + //提取满减信息 + WebElement redElm = promItem.findElement(By.className("hl_red")); + String text = redElm.getText(); + if (StrUtil.isNotEmpty(text)) { + //提取满减 + String bg = promItem.findElement(By.className("hl_red_bg")).getText(); + String reg = "[\\u4E00-\\u9FA5]+"; + List list = Stream.of(reg.split(reg)).filter(StrUtil::isNotEmpty).collect(Collectors.toList()); + if (list.size() > 0 && list.stream().anyMatch(NumberUtil::isNumber)) { + //计算满减价格 + //判断价格是否符合满减数 + if ("满减".equals(bg) && list.size() > 2) { + BigDecimal skuPrice = NumberUtil.toBigDecimal(productInfo.getPrice()); + if (skuPrice.compareTo(NumberUtil.toBigDecimal(list.get(0))) >= 0) { + BigDecimal discountPrice = NumberUtil.toBigDecimal(list.get(1)); + //设置实际价格 + productInfo.setActualPrice(skuPrice.subtract(discountPrice).toString()); + } + } + } + } + } + + return productInfo; + } + + private List searchJdProducts(WebDriver webDriver, String keywords) { + //打开京东地址 + webDriver.get("https://search.jd.com/Search?keyword=" + keywords); + String title = webDriver.getTitle(); + List elementList = webDriver.findElements(By.className("gl-i-wrap")); + List productInfos = elementList.stream().map(webElement -> { + ProductInfo productInfo = new ProductInfo(); + productInfo.setDescription(webElement.findElement(By.className("p-name")).getText()); + String price = webElement.findElement(By.className("p-price")).getText(); + price = price.replaceAll("¥", ""); +// productInfo.setMaxPrice(price); + return productInfo; + }).collect(Collectors.toList()); + return productInfos; + } + + @SneakyThrows + private List searchTbProducts(WebDriver webDriver, String keyWords) { + //打开京东地址 + webDriver.get("https://login.taobao.com/member/login.jhtml?tpl_redirect_url=https%3A%2F%2Fwww.tmall.com&style=miniall&enup=true&newMini2=true&full_redirect=true&sub=true&from=tmall&allp=assets_css%3D3.0.10/login_pc.css&pms=1650640249767"); + Thread.sleep(10 * 1000L); + + // 预登录 + webDriver.findElement(By.xpath("//input[@name='fm-login-id']")).sendKeys(account); + webDriver.findElement(By.xpath("//input[@name='fm-login-password']")).sendKeys(pwd); + webDriver.findElement(By.xpath("//*[@class=\"fm-button fm-submit password-login\"]")).click(); + + String oldHandler = webDriver.getWindowHandle(); + webDriver.findElement(By.className("SearchInput--searchInputContent--1USWNEl")).sendKeys(keyWords); + Thread.sleep(10 * 1000L); + webDriver.findElement(By.className("SearchInput--searchButton--1Sz2UIn")).click(); + Thread.sleep(30 * 1000L); + // 获取当前handler + + Set sets = webDriver.getWindowHandles(); + String newWindow = sets.stream().filter(handler -> !oldHandler.equals(handler)).findFirst().get(); + webDriver.switchTo().window(newWindow); + + List tmElementList = webDriver.findElements(By.className("product-iWrap")); + List productInfos = tmElementList.stream().map(pElement -> { + ProductInfo productInfo = new ProductInfo(); + productInfo.setDescription(pElement.findElement(By.className("productTitle")).getText()); + String price = pElement.findElement(By.className("productPrice")).getText(); + System.out.println(price); + price = price.replaceAll("¥", ""); +// productInfo.setMaxPrice(price); + return productInfo; + }).collect(Collectors.toList()); + return productInfos; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductServiceImpl.java deleted file mode 100644 index 4e72150..0000000 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductServiceImpl.java +++ /dev/null @@ -1,144 +0,0 @@ -package com.casic.missiles.modular.system.service.impl; - -import com.casic.missiles.modular.system.model.ProductInfo; -import com.casic.missiles.modular.system.service.IProductSearchService; -import lombok.SneakyThrows; -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.chrome.ChromeOptions; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; - -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -/** - * 产品搜索实例 - * - * @author lwh - */ -@Component -public class ProductServiceImpl implements IProductSearchService { - @Value("${casic.webdriver.path}") - private String path; - @Override - public List searchProducts(String type) { - //驱动地址 - String chromedriver = "D:\\dev-soft\\seleuim-chmod\\chromedriver.exe"; - System.setProperty("webdriver.chrome.driver", path); - ChromeOptions option = new ChromeOptions(); - //去掉chrome 正受到自动测试软件的控制 - option.addArguments("disable-infobars"); - //开启开发者模式 - option.setExperimentalOption("excludeSwitches", Collections.singletonList("enable-automation")); - option.addArguments("--disable-blink-features"); - option.addArguments("--disable-blink-features=AutomationControlled"); - //初始化一个chrome浏览器实例 - WebDriver webDriver = new ChromeDriver(option); - //最大化窗口 - webDriver.manage().window().maximize(); - //设置隐性等待时间 - webDriver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS); - - return searchJdProducts(webDriver); - } - - private List searchJdProducts(WebDriver webDriver) { - //打开京东地址 - webDriver.get("https://search.jd.com/Search?keyword=%E8%8B%B9%E6%9E%9C13"); - String title = webDriver.getTitle(); - List elementList = webDriver.findElements(By.className("gl-i-wrap")); - List productInfos = elementList.stream().map(webElement -> { - ProductInfo productInfo = new ProductInfo(); - productInfo.setDescription(webElement.findElement(By.className("p-name")).getText()); - productInfo.setPrice(webElement.findElement(By.className("p-price")).getText()); - return productInfo; - }).collect(Collectors.toList()); - return productInfos; - } - - @SneakyThrows - private List searchTbProducts(WebDriver webDriver) { - //打开京东地址 - webDriver.get("https://login.taobao.com/member/login.jhtml?tpl_redirect_url=https%3A%2F%2Fwww.tmall.com&style=miniall&enup=true&newMini2=true&full_redirect=true&sub=true&from=tmall&allp=assets_css%3D3.0.10/login_pc.css&pms=1650640249767"); - Thread.sleep(10 * 1000L); - - // 预登录 - webDriver.findElement(By.xpath("//input[@name='fm-login-id']")).sendKeys("18600202639"); - webDriver.findElement(By.xpath("//input[@name='fm-login-password']")).sendKeys("19881126yu"); - webDriver.findElement(By.xpath("//*[@class=\"fm-button fm-submit password-login\"]")).click(); - - String oldHandler = webDriver.getWindowHandle(); - webDriver.findElement(By.className("SearchInput--searchInputContent--1USWNEl")).sendKeys("苹果13"); - Thread.sleep(10 * 1000L); - webDriver.findElement(By.className("SearchInput--searchButton--1Sz2UIn")).click(); - Thread.sleep(30 * 1000L); - // 获取当前handler - - Set sets = webDriver.getWindowHandles(); - String newWindow = sets.stream().filter(handler -> !oldHandler.equals(handler)).findFirst().get(); - webDriver.switchTo().window(newWindow); - - List tmElementList = webDriver.findElements(By.className("product-iWrap")); - List productInfos = tmElementList.stream().map(pElement -> { - ProductInfo productInfo = new ProductInfo(); - productInfo.setDescription(pElement.findElement(By.className("productPrice")).getText()); - productInfo.setPrice(pElement.findElement(By.className("productTitle")).getText()); - return productInfo; - }).collect(Collectors.toList()); - return productInfos; - } - - public static void main(String[] args) throws InterruptedException { - //驱动地址 - String chromedriver = "D:\\dev-soft\\seleuim-chmod\\chromedriver.exe"; - System.setProperty("webdriver.chrome.driver", chromedriver); - ChromeOptions option = new ChromeOptions(); - //去掉chrome 正受到自动测试软件的控制 - option.addArguments("disable-infobars"); - //开启开发者模式 - option.setExperimentalOption("excludeSwitches", Collections.singletonList("enable-automation")); - option.addArguments("--disable-blink-features"); - option.addArguments("--disable-blink-features=AutomationControlled"); - //初始化一个chrome浏览器实例 - WebDriver webDriver = new ChromeDriver(option); - //最大化窗口 - webDriver.manage().window().maximize(); - //设置隐性等待时间 - webDriver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS); - //打开京东地址 - webDriver.get("https://login.taobao.com/member/login.jhtml?tpl_redirect_url=https%3A%2F%2Fwww.tmall.com&style=miniall&enup=true&newMini2=true&full_redirect=true&sub=true&from=tmall&allp=assets_css%3D3.0.10/login_pc.css&pms=1650640249767"); - Thread.sleep(10 * 1000L); - - // 预登录 - webDriver.findElement(By.xpath("//input[@name='fm-login-id']")).sendKeys("18600202639"); - webDriver.findElement(By.xpath("//input[@name='fm-login-password']")).sendKeys("19881126yu"); - webDriver.findElement(By.xpath("//*[@class=\"fm-button fm-submit password-login\"]")).click(); - - String oldHandler = webDriver.getWindowHandle(); - webDriver.findElement(By.className("SearchInput--searchInputContent--1USWNEl")).sendKeys("苹果13"); - Thread.sleep(10 * 1000L); - webDriver.findElement(By.className("SearchInput--searchButton--1Sz2UIn")).click(); - Thread.sleep(30 * 1000L); - // 获取当前handler - - Set sets = webDriver.getWindowHandles(); - String newWindow = sets.stream().filter(handler -> !oldHandler.equals(handler)).findFirst().get(); - webDriver.switchTo().window(newWindow); - - List tmElementList = webDriver.findElements(By.className("product-iWrap")); - List productInfos = tmElementList.stream().map(pElement -> { - ProductInfo productInfo = new ProductInfo(); - productInfo.setDescription(pElement.findElement(By.className("productPrice")).getText()); - productInfo.setPrice(pElement.findElement(By.className("productTitle")).getText()); - return productInfo; - }).collect(Collectors.toList()); - - System.out.println(productInfos); - } -} diff --git a/casic-web/pom.xml b/casic-web/pom.xml index 35f0017..eb21475 100644 --- a/casic-web/pom.xml +++ b/casic-web/pom.xml @@ -78,11 +78,6 @@ casic-admin-support ${admin.version} - - com.casic - casic-job-starter - ${extension.version} - diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 0e47785..0adbba2 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -37,9 +37,19 @@ com.casic + casic-job-quartz + ${extension.version} + + + com.casic casic-selenium-core ${extension.version} + + com.google.guava + guava + 30.1-jre + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java new file mode 100644 index 0000000..9dc3950 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java @@ -0,0 +1,94 @@ +package com.casic.missiles.modular.system.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.BaseController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.system.model.ProductInfo; +import com.casic.missiles.modular.system.service.IProductInfoService; +import com.casic.missiles.modular.system.service.ISearchKeysService; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 商品信息管理控制器 + * + * @author dev + * @Date 2022-05-05 15:46:28 + */ +@Controller +@RequestMapping("/productInfo") +public class ProductInfoController extends BaseController { + @Resource + private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + + /** + * 获取商品信息管理列表 + */ + @RequestMapping(value = "/list") + @ResponseBody + public Object list(String condition) { + return productInfoService.list(null); + } + + /** + * 获取商品信息管理分页列表 + */ + @RequestMapping(value = "/listPage") + @ResponseBody + public Object listPage(String condition) { + Page page = PageFactory.defaultPage(); + QueryWrapper query = new QueryWrapper<>(); + List productInfos = productInfoService.searchDbProductPricePage(condition, page); + page.setRecords(productInfos); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 新增商品信息管理 + */ + @RequestMapping(value = "/add") + @ResponseBody + public Object add(ProductInfo productInfo) { + productInfoService.save(productInfo); + return ResponseData.success(); + } + + /** + * 删除商品信息管理 + */ + @RequestMapping(value = "/delete") + @ResponseBody + public Object delete(@RequestParam String productInfoId) { + productInfoService.removeById(productInfoId); + return ResponseData.success(); + } + + /** + * 修改商品信息管理 + */ + @RequestMapping(value = "/update") + @ResponseBody + public Object update(ProductInfo productInfo) { + productInfoService.updateById(productInfo); + return ResponseData.success(); + } + + /** + * 商品信息管理详情 + */ + @RequestMapping(value = "/detail/{productInfoId}") + @ResponseBody + public Object detail(@PathVariable("productInfoId") String productInfoId) { + return ResponseData.success(productInfoService.getById(productInfoId)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java index 78c1892..446be24 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java @@ -1,11 +1,14 @@ package com.casic.missiles.modular.system.controller; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.BaseController; import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.form.IdForms; import com.casic.missiles.model.response.ResponseData; import com.casic.missiles.modular.system.model.SearchKeys; +import com.casic.missiles.modular.system.service.IProductInfoService; import com.casic.missiles.modular.system.service.ISearchKeysService; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; @@ -24,7 +27,25 @@ @Resource private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + /** + * 获取关键字管理列表 + */ + @GetMapping(value = "/loadSearch") + @ResponseBody + public Object loadSearch(String condition) { + new Thread(){ + @Override + public void run() { + super.run(); + productInfoService.searchProducts(null); + } + }.start(); + + return ResponseData.success(); + } /** * 获取关键字管理列表 @@ -43,6 +64,10 @@ public Object listPage(String condition) { Page page = PageFactory.defaultPage(); QueryWrapper query = new QueryWrapper<>(); + if (StrUtil.isNotEmpty(condition)) { + query.like("keywords", condition); + } + page = searchKeysService.page(page, query); return ResponseData.success(super.packForBT(page)); } @@ -52,7 +77,7 @@ */ @PostMapping(value = "/add") @ResponseBody - public Object add(SearchKeys searchKeys) { + public Object add(@RequestBody SearchKeys searchKeys) { searchKeysService.save(searchKeys); return ResponseData.success(); } @@ -62,8 +87,8 @@ */ @PostMapping(value = "/delete") @ResponseBody - public Object delete(@RequestParam String searchKeysId) { - searchKeysService.removeById(searchKeysId); + public Object delete(@RequestBody IdForms searchKeysIds) { + searchKeysService.removeByIds(searchKeysIds.getIds()); return ResponseData.success(); } @@ -73,7 +98,7 @@ */ @PostMapping(value = "/update") @ResponseBody - public Object update(SearchKeys searchKeys) { + public Object update(@RequestBody SearchKeys searchKeys) { searchKeysService.updateById(searchKeys); return ResponseData.success(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java new file mode 100644 index 0000000..c3d1185 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.system.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.system.model.ProductInfo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 商品信息 Mapper 接口 + *

+ * + * @author stylefeng123 + * @since 2022-05-05 + */ +public interface ProductInfoMapper extends BaseMapper { + + /** + * 产品数据检索 + * + * @return 产品价格列表 + */ + List searchDbProductPricePage(@Param("keywords") String keywords, @Param("page") Page page); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml new file mode 100644 index 0000000..99c83ba --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + id, max_price AS maxPrice, min_price AS minPrice, description + + + + '%' || #{keywords}|| '%' + + + CONCAT('%',#{keywords},'%') + + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml index 348f2a0..4f41b58 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml @@ -5,14 +5,14 @@ - + - id, keys, search_time AS searchTime, keep_days AS keepDays + id, keywords, search_time AS searchTime, keep_days AS keepDays diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java b/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java new file mode 100644 index 0000000..df0766c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java @@ -0,0 +1,38 @@ +package com.casic.missiles.modular.system.job; + +import cn.hutool.core.util.RandomUtil; +import com.casic.missiles.modular.system.service.IProductInfoService; +import lombok.SneakyThrows; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.math.BigDecimal; + +/** + * @ClassName QuartzJob + * @Description 依赖casic-job-quartz,并在CasicApplication上增加注解 @EnableScheduling + * @Author lwh + * @Date 2021/2/5 11:20 + * @Version 1.0 + */ +@Component +public class QuartzJob { + @Resource + private IProductInfoService productInfoService; + + /** + * + */ + @SneakyThrows + @Scheduled(cron = "0 0 10,14,16 * * ?") + public void execute() { + try { + Thread.sleep(RandomUtil.randomBigDecimal(new BigDecimal(2000)).intValue()); + System.out.println("-----Thread ID 每60秒执行一次"); + productInfoService.searchProducts(null); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java index 03190bf..d5c4ecd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java @@ -1,14 +1,74 @@ package com.casic.missiles.modular.system.model; +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import com.casic.missiles.core.base.json.DateDeserializer; import lombok.Data; +import java.util.Date; + /** - * 产品信息 + *

+ * 商品信息 + *

* - * @author lenovo + * @author stylefeng123 + * @since 2022-05-05 */ @Data -public class ProductInfo { - private String description; +@TableName("reptile_product_info") +public class ProductInfo extends Model { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + private Long id; + /** + * 页面价格 + */ + @TableField("price") private String price; + /** + * 满减价格 + */ + @TableField("actual_price") + private String actualPrice; + /** + * 优惠信息 + */ + @TableField("discount") + private String discount; + + /** + * 其他信息 + */ + private String description; + + + @TableField("key_id") + private Long keyId; + + /** + * 0 页面无效 1 价格偏高 + */ + private String flag; + @JSONField(serializeUsing = DateDeserializer.class) + @TableField("create_time") + private Date createTime; + @TableField(exist = false) + private String skuName; + @TableField(exist = false) + private String skuUrl; + + @Override + public String toString() { + return "ProductInfo{" + + "id=" + id + + ", description=" + description + + "}"; + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java index 09eb7ee..ed01581 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java @@ -1,8 +1,10 @@ package com.casic.missiles.modular.system.model; +import com.alibaba.fastjson.annotation.JSONField; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.extension.activerecord.Model; +import com.casic.missiles.core.base.json.DateDeserializer; import lombok.Data; import java.util.Date; @@ -26,12 +28,24 @@ */ private Long id; /** - * 检索关键字 + * 商品名称 */ - private String keys; + @TableField("sku_name") + private String skuName; + /** + * 商品url + */ + @TableField("sku_url") + private String skuUrl; + /** + * 设定价格 + */ + @TableField("price") + private String price; /** * 最后检索时间 */ + @JSONField(serializeUsing = DateDeserializer.class) @TableField("search_time") private Date searchTime; /** @@ -40,12 +54,10 @@ @TableField("keep_days") private Integer keepDays; - @Override public String toString() { return "SearchKeys{" + "id=" + id + - ", keys=" + keys + ", searchTime=" + searchTime + ", keepDays=" + keepDays + "}"; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/service/IProductInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/system/service/IProductInfoService.java new file mode 100644 index 0000000..f6a8a35 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/service/IProductInfoService.java @@ -0,0 +1,30 @@ +package com.casic.missiles.modular.system.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.missiles.modular.system.model.ProductInfo; + +import java.util.List; + +/** + *

+ * 商品信息 服务类 + *

+ * + * @author stylefeng123 + * @since 2022-05-05 + */ +public interface IProductInfoService extends IService { + /** + * 检索商品接口定义 + * @param type jd tm + * @return + */ + public List searchProducts(String type); + /** + * 检索商品价格信息 + * @param type jd tm + * @return + */ + public List searchDbProductPricePage(String type, Page page); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductInfoServiceImpl.java new file mode 100644 index 0000000..e912cfd --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductInfoServiceImpl.java @@ -0,0 +1,218 @@ +package com.casic.missiles.modular.system.service.impl; + +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.modular.system.dao.ProductInfoMapper; +import com.casic.missiles.modular.system.model.ProductInfo; +import com.casic.missiles.modular.system.model.SearchKeys; +import com.casic.missiles.modular.system.service.IProductInfoService; +import com.casic.missiles.modular.system.service.ISearchKeysService; +import lombok.SneakyThrows; +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.chrome.ChromeDriver; +import org.openqa.selenium.chrome.ChromeOptions; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + *

+ * 商品信息 服务实现类 + *

+ * + * @author stylefeng123 + * @since 2022-05-05 + */ +@Service +public class ProductInfoServiceImpl extends ServiceImpl implements IProductInfoService { + @Value("${casic.webdriver.path}") + private String path; + @Value("${casic.tm.account}") + private String account; + @Value("${casic.tm.pwd}") + private String pwd; + @Resource + private ISearchKeysService searchKeysService; + + @Override + public List searchProducts(String type) { + System.setProperty("webdriver.chrome.driver", path); + List searchKeys = searchKeysService.list(); + Date searchTime = new Date(); + WebDriver webDriver = null; + try { + //驱动地址 + ChromeOptions option = new ChromeOptions(); + //去掉chrome 正受到自动测试软件的控制 + option.addArguments("disable-infobars"); + //开启开发者模式 + option.setExperimentalOption("excludeSwitches", Collections.singletonList("enable-automation")); + option.addArguments("--disable-blink-features"); + option.addArguments("--disable-blink-features=AutomationControlled"); + //初始化一个chrome浏览器实例 + webDriver = new ChromeDriver(option); + //最大化窗口 + webDriver.manage().window().maximize(); + //设置隐性等待时间 + webDriver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS); + for (SearchKeys searchKey : searchKeys) { +// List productInfos = searchJdProducts(webDriver, searchKey.getKeywords()); +// ProductInfo maxJd = productInfos.stream().max(Comparator.comparing(ProductInfo::getMaxPrice)).get(); +// ProductInfo minJd = productInfos.stream().min(Comparator.comparing(ProductInfo::getMaxPrice)).get(); +// // 过滤价格区间 +// ProductInfo info = new ProductInfo(); +// info.setKeyId(searchKey.getId()); +// info.setCreateTime(searchTime); +// info.setMaxPrice(maxJd.getMaxPrice()); +// info.setMinPrice(minJd.getMaxPrice()); +// StringBuilder jdStr = new StringBuilder(); +// jdStr.append("京东:").append(minJd.getDescription()).append("---").append(maxJd.getDescription()).append(" "); +// // 过滤天猫信息 +// List productTmInfos = searchTbProducts(webDriver, searchKey.getKeywords()); +// ProductInfo maxTb = productTmInfos.stream().max(Comparator.comparing(ProductInfo::getMaxPrice)).get(); +// ProductInfo minTb = productTmInfos.stream().min(Comparator.comparing(ProductInfo::getMaxPrice)).get(); +// info.setMaxTmPrice(maxTb.getMaxPrice()); +// info.setMinTmPrice(minTb.getMaxPrice()); +// jdStr.append("天猫:").append(minTb.getDescription()).append("---").append(maxTb.getDescription()).append(" "); + +// info.setDescription(jdStr.toString()); +// this.save(info); + searchKey.setSearchTime(searchTime); + searchKeysService.updateById(searchKey); + } + + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (webDriver != null) { + webDriver.close(); + webDriver.quit(); + } + } + return new ArrayList<>(); + } + + @Override + public List searchDbProductPricePage(String keywords, Page page) { + return this.baseMapper.searchDbProductPricePage(keywords, page); + } + + private ProductInfo searchJdDetail(WebDriver webDriver, String url) { + ProductInfo productInfo = new ProductInfo(); + //打开京东地址 + webDriver.get(url); + String title = webDriver.getTitle(); + WebElement skuEl = webDriver.findElement(By.className("sku-name")); + if (skuEl != null) { + String skuName = skuEl.getText(); + productInfo.setDescription(skuName); + } else { + productInfo.setFlag("1"); + } + + // NO1 读取价格信息 + WebElement priceEl = webDriver.findElement(By.className("p-price")); + if (priceEl != null) { + WebElement webP = priceEl.findElement(By.className("price")); + if (webP != null && NumberUtil.isNumber(webP.getText())) { + //设置页面价格 + productInfo.setPrice(webP.getText()); + } else { + //页面元素获取异常 判定为页面失效 + productInfo.setFlag("1"); + } + } else { + //页面元素获取异常 判定为页面失效 + productInfo.setFlag("1"); + } + + // NO2 读取打折信息 + WebElement promItem = webDriver.findElement(By.className("prom-item")); + if (promItem != null) { + //提取满减信息 + WebElement redElm = promItem.findElement(By.className("hl_red")); + String text = redElm.getText(); + if (StrUtil.isNotEmpty(text)) { + //提取满减 + String bg = promItem.findElement(By.className("hl_red_bg")).getText(); + String reg = "[\\u4E00-\\u9FA5]+"; + List list = Stream.of(reg.split(reg)).filter(StrUtil::isNotEmpty).collect(Collectors.toList()); + if (list.size() > 0 && list.stream().anyMatch(NumberUtil::isNumber)) { + //计算满减价格 + //判断价格是否符合满减数 + if ("满减".equals(bg) && list.size() > 2) { + BigDecimal skuPrice = NumberUtil.toBigDecimal(productInfo.getPrice()); + if (skuPrice.compareTo(NumberUtil.toBigDecimal(list.get(0))) >= 0) { + BigDecimal discountPrice = NumberUtil.toBigDecimal(list.get(1)); + //设置实际价格 + productInfo.setActualPrice(skuPrice.subtract(discountPrice).toString()); + } + } + } + } + } + + return productInfo; + } + + private List searchJdProducts(WebDriver webDriver, String keywords) { + //打开京东地址 + webDriver.get("https://search.jd.com/Search?keyword=" + keywords); + String title = webDriver.getTitle(); + List elementList = webDriver.findElements(By.className("gl-i-wrap")); + List productInfos = elementList.stream().map(webElement -> { + ProductInfo productInfo = new ProductInfo(); + productInfo.setDescription(webElement.findElement(By.className("p-name")).getText()); + String price = webElement.findElement(By.className("p-price")).getText(); + price = price.replaceAll("¥", ""); +// productInfo.setMaxPrice(price); + return productInfo; + }).collect(Collectors.toList()); + return productInfos; + } + + @SneakyThrows + private List searchTbProducts(WebDriver webDriver, String keyWords) { + //打开京东地址 + webDriver.get("https://login.taobao.com/member/login.jhtml?tpl_redirect_url=https%3A%2F%2Fwww.tmall.com&style=miniall&enup=true&newMini2=true&full_redirect=true&sub=true&from=tmall&allp=assets_css%3D3.0.10/login_pc.css&pms=1650640249767"); + Thread.sleep(10 * 1000L); + + // 预登录 + webDriver.findElement(By.xpath("//input[@name='fm-login-id']")).sendKeys(account); + webDriver.findElement(By.xpath("//input[@name='fm-login-password']")).sendKeys(pwd); + webDriver.findElement(By.xpath("//*[@class=\"fm-button fm-submit password-login\"]")).click(); + + String oldHandler = webDriver.getWindowHandle(); + webDriver.findElement(By.className("SearchInput--searchInputContent--1USWNEl")).sendKeys(keyWords); + Thread.sleep(10 * 1000L); + webDriver.findElement(By.className("SearchInput--searchButton--1Sz2UIn")).click(); + Thread.sleep(30 * 1000L); + // 获取当前handler + + Set sets = webDriver.getWindowHandles(); + String newWindow = sets.stream().filter(handler -> !oldHandler.equals(handler)).findFirst().get(); + webDriver.switchTo().window(newWindow); + + List tmElementList = webDriver.findElements(By.className("product-iWrap")); + List productInfos = tmElementList.stream().map(pElement -> { + ProductInfo productInfo = new ProductInfo(); + productInfo.setDescription(pElement.findElement(By.className("productTitle")).getText()); + String price = pElement.findElement(By.className("productPrice")).getText(); + System.out.println(price); + price = price.replaceAll("¥", ""); +// productInfo.setMaxPrice(price); + return productInfo; + }).collect(Collectors.toList()); + return productInfos; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductServiceImpl.java deleted file mode 100644 index 4e72150..0000000 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductServiceImpl.java +++ /dev/null @@ -1,144 +0,0 @@ -package com.casic.missiles.modular.system.service.impl; - -import com.casic.missiles.modular.system.model.ProductInfo; -import com.casic.missiles.modular.system.service.IProductSearchService; -import lombok.SneakyThrows; -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.chrome.ChromeOptions; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; - -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -/** - * 产品搜索实例 - * - * @author lwh - */ -@Component -public class ProductServiceImpl implements IProductSearchService { - @Value("${casic.webdriver.path}") - private String path; - @Override - public List searchProducts(String type) { - //驱动地址 - String chromedriver = "D:\\dev-soft\\seleuim-chmod\\chromedriver.exe"; - System.setProperty("webdriver.chrome.driver", path); - ChromeOptions option = new ChromeOptions(); - //去掉chrome 正受到自动测试软件的控制 - option.addArguments("disable-infobars"); - //开启开发者模式 - option.setExperimentalOption("excludeSwitches", Collections.singletonList("enable-automation")); - option.addArguments("--disable-blink-features"); - option.addArguments("--disable-blink-features=AutomationControlled"); - //初始化一个chrome浏览器实例 - WebDriver webDriver = new ChromeDriver(option); - //最大化窗口 - webDriver.manage().window().maximize(); - //设置隐性等待时间 - webDriver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS); - - return searchJdProducts(webDriver); - } - - private List searchJdProducts(WebDriver webDriver) { - //打开京东地址 - webDriver.get("https://search.jd.com/Search?keyword=%E8%8B%B9%E6%9E%9C13"); - String title = webDriver.getTitle(); - List elementList = webDriver.findElements(By.className("gl-i-wrap")); - List productInfos = elementList.stream().map(webElement -> { - ProductInfo productInfo = new ProductInfo(); - productInfo.setDescription(webElement.findElement(By.className("p-name")).getText()); - productInfo.setPrice(webElement.findElement(By.className("p-price")).getText()); - return productInfo; - }).collect(Collectors.toList()); - return productInfos; - } - - @SneakyThrows - private List searchTbProducts(WebDriver webDriver) { - //打开京东地址 - webDriver.get("https://login.taobao.com/member/login.jhtml?tpl_redirect_url=https%3A%2F%2Fwww.tmall.com&style=miniall&enup=true&newMini2=true&full_redirect=true&sub=true&from=tmall&allp=assets_css%3D3.0.10/login_pc.css&pms=1650640249767"); - Thread.sleep(10 * 1000L); - - // 预登录 - webDriver.findElement(By.xpath("//input[@name='fm-login-id']")).sendKeys("18600202639"); - webDriver.findElement(By.xpath("//input[@name='fm-login-password']")).sendKeys("19881126yu"); - webDriver.findElement(By.xpath("//*[@class=\"fm-button fm-submit password-login\"]")).click(); - - String oldHandler = webDriver.getWindowHandle(); - webDriver.findElement(By.className("SearchInput--searchInputContent--1USWNEl")).sendKeys("苹果13"); - Thread.sleep(10 * 1000L); - webDriver.findElement(By.className("SearchInput--searchButton--1Sz2UIn")).click(); - Thread.sleep(30 * 1000L); - // 获取当前handler - - Set sets = webDriver.getWindowHandles(); - String newWindow = sets.stream().filter(handler -> !oldHandler.equals(handler)).findFirst().get(); - webDriver.switchTo().window(newWindow); - - List tmElementList = webDriver.findElements(By.className("product-iWrap")); - List productInfos = tmElementList.stream().map(pElement -> { - ProductInfo productInfo = new ProductInfo(); - productInfo.setDescription(pElement.findElement(By.className("productPrice")).getText()); - productInfo.setPrice(pElement.findElement(By.className("productTitle")).getText()); - return productInfo; - }).collect(Collectors.toList()); - return productInfos; - } - - public static void main(String[] args) throws InterruptedException { - //驱动地址 - String chromedriver = "D:\\dev-soft\\seleuim-chmod\\chromedriver.exe"; - System.setProperty("webdriver.chrome.driver", chromedriver); - ChromeOptions option = new ChromeOptions(); - //去掉chrome 正受到自动测试软件的控制 - option.addArguments("disable-infobars"); - //开启开发者模式 - option.setExperimentalOption("excludeSwitches", Collections.singletonList("enable-automation")); - option.addArguments("--disable-blink-features"); - option.addArguments("--disable-blink-features=AutomationControlled"); - //初始化一个chrome浏览器实例 - WebDriver webDriver = new ChromeDriver(option); - //最大化窗口 - webDriver.manage().window().maximize(); - //设置隐性等待时间 - webDriver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS); - //打开京东地址 - webDriver.get("https://login.taobao.com/member/login.jhtml?tpl_redirect_url=https%3A%2F%2Fwww.tmall.com&style=miniall&enup=true&newMini2=true&full_redirect=true&sub=true&from=tmall&allp=assets_css%3D3.0.10/login_pc.css&pms=1650640249767"); - Thread.sleep(10 * 1000L); - - // 预登录 - webDriver.findElement(By.xpath("//input[@name='fm-login-id']")).sendKeys("18600202639"); - webDriver.findElement(By.xpath("//input[@name='fm-login-password']")).sendKeys("19881126yu"); - webDriver.findElement(By.xpath("//*[@class=\"fm-button fm-submit password-login\"]")).click(); - - String oldHandler = webDriver.getWindowHandle(); - webDriver.findElement(By.className("SearchInput--searchInputContent--1USWNEl")).sendKeys("苹果13"); - Thread.sleep(10 * 1000L); - webDriver.findElement(By.className("SearchInput--searchButton--1Sz2UIn")).click(); - Thread.sleep(30 * 1000L); - // 获取当前handler - - Set sets = webDriver.getWindowHandles(); - String newWindow = sets.stream().filter(handler -> !oldHandler.equals(handler)).findFirst().get(); - webDriver.switchTo().window(newWindow); - - List tmElementList = webDriver.findElements(By.className("product-iWrap")); - List productInfos = tmElementList.stream().map(pElement -> { - ProductInfo productInfo = new ProductInfo(); - productInfo.setDescription(pElement.findElement(By.className("productPrice")).getText()); - productInfo.setPrice(pElement.findElement(By.className("productTitle")).getText()); - return productInfo; - }).collect(Collectors.toList()); - - System.out.println(productInfos); - } -} diff --git a/casic-web/pom.xml b/casic-web/pom.xml index 35f0017..eb21475 100644 --- a/casic-web/pom.xml +++ b/casic-web/pom.xml @@ -78,11 +78,6 @@ casic-admin-support ${admin.version} - - com.casic - casic-job-starter - ${extension.version} - diff --git a/casic-web/src/main/java/com/casic/missiles/ZkTest.java b/casic-web/src/main/java/com/casic/missiles/ZkTest.java deleted file mode 100644 index 7e5df40..0000000 --- a/casic-web/src/main/java/com/casic/missiles/ZkTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.casic.missiles; - -import com.casic.missiles.core.util.ZkUtil; -import org.apache.zookeeper.ZooDefs; - -public class ZkTest { - /** - * 白名单 IP添加(待增项) - * - * @param args - * @throws Exception - */ - public static void main(String[] args) throws Exception { - String zkPath = "/ss-job"; - String connectString = "localhost:2181"; - int perms = ZooDefs.Perms.ALL; - String scheme = "digest"; - String auth = "admin:Casic203"; - ZkUtil.addDigests(scheme,perms, null, connectString, zkPath); -// ZkUtil.deletePath(scheme, connectString, zkPath, auth, null); - } -} diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 0e47785..0adbba2 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -37,9 +37,19 @@ com.casic + casic-job-quartz + ${extension.version} + + + com.casic casic-selenium-core ${extension.version} + + com.google.guava + guava + 30.1-jre + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java new file mode 100644 index 0000000..9dc3950 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java @@ -0,0 +1,94 @@ +package com.casic.missiles.modular.system.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.BaseController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.system.model.ProductInfo; +import com.casic.missiles.modular.system.service.IProductInfoService; +import com.casic.missiles.modular.system.service.ISearchKeysService; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 商品信息管理控制器 + * + * @author dev + * @Date 2022-05-05 15:46:28 + */ +@Controller +@RequestMapping("/productInfo") +public class ProductInfoController extends BaseController { + @Resource + private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + + /** + * 获取商品信息管理列表 + */ + @RequestMapping(value = "/list") + @ResponseBody + public Object list(String condition) { + return productInfoService.list(null); + } + + /** + * 获取商品信息管理分页列表 + */ + @RequestMapping(value = "/listPage") + @ResponseBody + public Object listPage(String condition) { + Page page = PageFactory.defaultPage(); + QueryWrapper query = new QueryWrapper<>(); + List productInfos = productInfoService.searchDbProductPricePage(condition, page); + page.setRecords(productInfos); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 新增商品信息管理 + */ + @RequestMapping(value = "/add") + @ResponseBody + public Object add(ProductInfo productInfo) { + productInfoService.save(productInfo); + return ResponseData.success(); + } + + /** + * 删除商品信息管理 + */ + @RequestMapping(value = "/delete") + @ResponseBody + public Object delete(@RequestParam String productInfoId) { + productInfoService.removeById(productInfoId); + return ResponseData.success(); + } + + /** + * 修改商品信息管理 + */ + @RequestMapping(value = "/update") + @ResponseBody + public Object update(ProductInfo productInfo) { + productInfoService.updateById(productInfo); + return ResponseData.success(); + } + + /** + * 商品信息管理详情 + */ + @RequestMapping(value = "/detail/{productInfoId}") + @ResponseBody + public Object detail(@PathVariable("productInfoId") String productInfoId) { + return ResponseData.success(productInfoService.getById(productInfoId)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java index 78c1892..446be24 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java @@ -1,11 +1,14 @@ package com.casic.missiles.modular.system.controller; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.BaseController; import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.form.IdForms; import com.casic.missiles.model.response.ResponseData; import com.casic.missiles.modular.system.model.SearchKeys; +import com.casic.missiles.modular.system.service.IProductInfoService; import com.casic.missiles.modular.system.service.ISearchKeysService; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; @@ -24,7 +27,25 @@ @Resource private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + /** + * 获取关键字管理列表 + */ + @GetMapping(value = "/loadSearch") + @ResponseBody + public Object loadSearch(String condition) { + new Thread(){ + @Override + public void run() { + super.run(); + productInfoService.searchProducts(null); + } + }.start(); + + return ResponseData.success(); + } /** * 获取关键字管理列表 @@ -43,6 +64,10 @@ public Object listPage(String condition) { Page page = PageFactory.defaultPage(); QueryWrapper query = new QueryWrapper<>(); + if (StrUtil.isNotEmpty(condition)) { + query.like("keywords", condition); + } + page = searchKeysService.page(page, query); return ResponseData.success(super.packForBT(page)); } @@ -52,7 +77,7 @@ */ @PostMapping(value = "/add") @ResponseBody - public Object add(SearchKeys searchKeys) { + public Object add(@RequestBody SearchKeys searchKeys) { searchKeysService.save(searchKeys); return ResponseData.success(); } @@ -62,8 +87,8 @@ */ @PostMapping(value = "/delete") @ResponseBody - public Object delete(@RequestParam String searchKeysId) { - searchKeysService.removeById(searchKeysId); + public Object delete(@RequestBody IdForms searchKeysIds) { + searchKeysService.removeByIds(searchKeysIds.getIds()); return ResponseData.success(); } @@ -73,7 +98,7 @@ */ @PostMapping(value = "/update") @ResponseBody - public Object update(SearchKeys searchKeys) { + public Object update(@RequestBody SearchKeys searchKeys) { searchKeysService.updateById(searchKeys); return ResponseData.success(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java new file mode 100644 index 0000000..c3d1185 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.system.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.system.model.ProductInfo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 商品信息 Mapper 接口 + *

+ * + * @author stylefeng123 + * @since 2022-05-05 + */ +public interface ProductInfoMapper extends BaseMapper { + + /** + * 产品数据检索 + * + * @return 产品价格列表 + */ + List searchDbProductPricePage(@Param("keywords") String keywords, @Param("page") Page page); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml new file mode 100644 index 0000000..99c83ba --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + id, max_price AS maxPrice, min_price AS minPrice, description + + + + '%' || #{keywords}|| '%' + + + CONCAT('%',#{keywords},'%') + + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml index 348f2a0..4f41b58 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml @@ -5,14 +5,14 @@ - + - id, keys, search_time AS searchTime, keep_days AS keepDays + id, keywords, search_time AS searchTime, keep_days AS keepDays diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java b/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java new file mode 100644 index 0000000..df0766c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java @@ -0,0 +1,38 @@ +package com.casic.missiles.modular.system.job; + +import cn.hutool.core.util.RandomUtil; +import com.casic.missiles.modular.system.service.IProductInfoService; +import lombok.SneakyThrows; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.math.BigDecimal; + +/** + * @ClassName QuartzJob + * @Description 依赖casic-job-quartz,并在CasicApplication上增加注解 @EnableScheduling + * @Author lwh + * @Date 2021/2/5 11:20 + * @Version 1.0 + */ +@Component +public class QuartzJob { + @Resource + private IProductInfoService productInfoService; + + /** + * + */ + @SneakyThrows + @Scheduled(cron = "0 0 10,14,16 * * ?") + public void execute() { + try { + Thread.sleep(RandomUtil.randomBigDecimal(new BigDecimal(2000)).intValue()); + System.out.println("-----Thread ID 每60秒执行一次"); + productInfoService.searchProducts(null); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java index 03190bf..d5c4ecd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java @@ -1,14 +1,74 @@ package com.casic.missiles.modular.system.model; +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import com.casic.missiles.core.base.json.DateDeserializer; import lombok.Data; +import java.util.Date; + /** - * 产品信息 + *

+ * 商品信息 + *

* - * @author lenovo + * @author stylefeng123 + * @since 2022-05-05 */ @Data -public class ProductInfo { - private String description; +@TableName("reptile_product_info") +public class ProductInfo extends Model { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + private Long id; + /** + * 页面价格 + */ + @TableField("price") private String price; + /** + * 满减价格 + */ + @TableField("actual_price") + private String actualPrice; + /** + * 优惠信息 + */ + @TableField("discount") + private String discount; + + /** + * 其他信息 + */ + private String description; + + + @TableField("key_id") + private Long keyId; + + /** + * 0 页面无效 1 价格偏高 + */ + private String flag; + @JSONField(serializeUsing = DateDeserializer.class) + @TableField("create_time") + private Date createTime; + @TableField(exist = false) + private String skuName; + @TableField(exist = false) + private String skuUrl; + + @Override + public String toString() { + return "ProductInfo{" + + "id=" + id + + ", description=" + description + + "}"; + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java index 09eb7ee..ed01581 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java @@ -1,8 +1,10 @@ package com.casic.missiles.modular.system.model; +import com.alibaba.fastjson.annotation.JSONField; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.extension.activerecord.Model; +import com.casic.missiles.core.base.json.DateDeserializer; import lombok.Data; import java.util.Date; @@ -26,12 +28,24 @@ */ private Long id; /** - * 检索关键字 + * 商品名称 */ - private String keys; + @TableField("sku_name") + private String skuName; + /** + * 商品url + */ + @TableField("sku_url") + private String skuUrl; + /** + * 设定价格 + */ + @TableField("price") + private String price; /** * 最后检索时间 */ + @JSONField(serializeUsing = DateDeserializer.class) @TableField("search_time") private Date searchTime; /** @@ -40,12 +54,10 @@ @TableField("keep_days") private Integer keepDays; - @Override public String toString() { return "SearchKeys{" + "id=" + id + - ", keys=" + keys + ", searchTime=" + searchTime + ", keepDays=" + keepDays + "}"; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/service/IProductInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/system/service/IProductInfoService.java new file mode 100644 index 0000000..f6a8a35 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/service/IProductInfoService.java @@ -0,0 +1,30 @@ +package com.casic.missiles.modular.system.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.missiles.modular.system.model.ProductInfo; + +import java.util.List; + +/** + *

+ * 商品信息 服务类 + *

+ * + * @author stylefeng123 + * @since 2022-05-05 + */ +public interface IProductInfoService extends IService { + /** + * 检索商品接口定义 + * @param type jd tm + * @return + */ + public List searchProducts(String type); + /** + * 检索商品价格信息 + * @param type jd tm + * @return + */ + public List searchDbProductPricePage(String type, Page page); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductInfoServiceImpl.java new file mode 100644 index 0000000..e912cfd --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductInfoServiceImpl.java @@ -0,0 +1,218 @@ +package com.casic.missiles.modular.system.service.impl; + +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.modular.system.dao.ProductInfoMapper; +import com.casic.missiles.modular.system.model.ProductInfo; +import com.casic.missiles.modular.system.model.SearchKeys; +import com.casic.missiles.modular.system.service.IProductInfoService; +import com.casic.missiles.modular.system.service.ISearchKeysService; +import lombok.SneakyThrows; +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.chrome.ChromeDriver; +import org.openqa.selenium.chrome.ChromeOptions; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + *

+ * 商品信息 服务实现类 + *

+ * + * @author stylefeng123 + * @since 2022-05-05 + */ +@Service +public class ProductInfoServiceImpl extends ServiceImpl implements IProductInfoService { + @Value("${casic.webdriver.path}") + private String path; + @Value("${casic.tm.account}") + private String account; + @Value("${casic.tm.pwd}") + private String pwd; + @Resource + private ISearchKeysService searchKeysService; + + @Override + public List searchProducts(String type) { + System.setProperty("webdriver.chrome.driver", path); + List searchKeys = searchKeysService.list(); + Date searchTime = new Date(); + WebDriver webDriver = null; + try { + //驱动地址 + ChromeOptions option = new ChromeOptions(); + //去掉chrome 正受到自动测试软件的控制 + option.addArguments("disable-infobars"); + //开启开发者模式 + option.setExperimentalOption("excludeSwitches", Collections.singletonList("enable-automation")); + option.addArguments("--disable-blink-features"); + option.addArguments("--disable-blink-features=AutomationControlled"); + //初始化一个chrome浏览器实例 + webDriver = new ChromeDriver(option); + //最大化窗口 + webDriver.manage().window().maximize(); + //设置隐性等待时间 + webDriver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS); + for (SearchKeys searchKey : searchKeys) { +// List productInfos = searchJdProducts(webDriver, searchKey.getKeywords()); +// ProductInfo maxJd = productInfos.stream().max(Comparator.comparing(ProductInfo::getMaxPrice)).get(); +// ProductInfo minJd = productInfos.stream().min(Comparator.comparing(ProductInfo::getMaxPrice)).get(); +// // 过滤价格区间 +// ProductInfo info = new ProductInfo(); +// info.setKeyId(searchKey.getId()); +// info.setCreateTime(searchTime); +// info.setMaxPrice(maxJd.getMaxPrice()); +// info.setMinPrice(minJd.getMaxPrice()); +// StringBuilder jdStr = new StringBuilder(); +// jdStr.append("京东:").append(minJd.getDescription()).append("---").append(maxJd.getDescription()).append(" "); +// // 过滤天猫信息 +// List productTmInfos = searchTbProducts(webDriver, searchKey.getKeywords()); +// ProductInfo maxTb = productTmInfos.stream().max(Comparator.comparing(ProductInfo::getMaxPrice)).get(); +// ProductInfo minTb = productTmInfos.stream().min(Comparator.comparing(ProductInfo::getMaxPrice)).get(); +// info.setMaxTmPrice(maxTb.getMaxPrice()); +// info.setMinTmPrice(minTb.getMaxPrice()); +// jdStr.append("天猫:").append(minTb.getDescription()).append("---").append(maxTb.getDescription()).append(" "); + +// info.setDescription(jdStr.toString()); +// this.save(info); + searchKey.setSearchTime(searchTime); + searchKeysService.updateById(searchKey); + } + + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (webDriver != null) { + webDriver.close(); + webDriver.quit(); + } + } + return new ArrayList<>(); + } + + @Override + public List searchDbProductPricePage(String keywords, Page page) { + return this.baseMapper.searchDbProductPricePage(keywords, page); + } + + private ProductInfo searchJdDetail(WebDriver webDriver, String url) { + ProductInfo productInfo = new ProductInfo(); + //打开京东地址 + webDriver.get(url); + String title = webDriver.getTitle(); + WebElement skuEl = webDriver.findElement(By.className("sku-name")); + if (skuEl != null) { + String skuName = skuEl.getText(); + productInfo.setDescription(skuName); + } else { + productInfo.setFlag("1"); + } + + // NO1 读取价格信息 + WebElement priceEl = webDriver.findElement(By.className("p-price")); + if (priceEl != null) { + WebElement webP = priceEl.findElement(By.className("price")); + if (webP != null && NumberUtil.isNumber(webP.getText())) { + //设置页面价格 + productInfo.setPrice(webP.getText()); + } else { + //页面元素获取异常 判定为页面失效 + productInfo.setFlag("1"); + } + } else { + //页面元素获取异常 判定为页面失效 + productInfo.setFlag("1"); + } + + // NO2 读取打折信息 + WebElement promItem = webDriver.findElement(By.className("prom-item")); + if (promItem != null) { + //提取满减信息 + WebElement redElm = promItem.findElement(By.className("hl_red")); + String text = redElm.getText(); + if (StrUtil.isNotEmpty(text)) { + //提取满减 + String bg = promItem.findElement(By.className("hl_red_bg")).getText(); + String reg = "[\\u4E00-\\u9FA5]+"; + List list = Stream.of(reg.split(reg)).filter(StrUtil::isNotEmpty).collect(Collectors.toList()); + if (list.size() > 0 && list.stream().anyMatch(NumberUtil::isNumber)) { + //计算满减价格 + //判断价格是否符合满减数 + if ("满减".equals(bg) && list.size() > 2) { + BigDecimal skuPrice = NumberUtil.toBigDecimal(productInfo.getPrice()); + if (skuPrice.compareTo(NumberUtil.toBigDecimal(list.get(0))) >= 0) { + BigDecimal discountPrice = NumberUtil.toBigDecimal(list.get(1)); + //设置实际价格 + productInfo.setActualPrice(skuPrice.subtract(discountPrice).toString()); + } + } + } + } + } + + return productInfo; + } + + private List searchJdProducts(WebDriver webDriver, String keywords) { + //打开京东地址 + webDriver.get("https://search.jd.com/Search?keyword=" + keywords); + String title = webDriver.getTitle(); + List elementList = webDriver.findElements(By.className("gl-i-wrap")); + List productInfos = elementList.stream().map(webElement -> { + ProductInfo productInfo = new ProductInfo(); + productInfo.setDescription(webElement.findElement(By.className("p-name")).getText()); + String price = webElement.findElement(By.className("p-price")).getText(); + price = price.replaceAll("¥", ""); +// productInfo.setMaxPrice(price); + return productInfo; + }).collect(Collectors.toList()); + return productInfos; + } + + @SneakyThrows + private List searchTbProducts(WebDriver webDriver, String keyWords) { + //打开京东地址 + webDriver.get("https://login.taobao.com/member/login.jhtml?tpl_redirect_url=https%3A%2F%2Fwww.tmall.com&style=miniall&enup=true&newMini2=true&full_redirect=true&sub=true&from=tmall&allp=assets_css%3D3.0.10/login_pc.css&pms=1650640249767"); + Thread.sleep(10 * 1000L); + + // 预登录 + webDriver.findElement(By.xpath("//input[@name='fm-login-id']")).sendKeys(account); + webDriver.findElement(By.xpath("//input[@name='fm-login-password']")).sendKeys(pwd); + webDriver.findElement(By.xpath("//*[@class=\"fm-button fm-submit password-login\"]")).click(); + + String oldHandler = webDriver.getWindowHandle(); + webDriver.findElement(By.className("SearchInput--searchInputContent--1USWNEl")).sendKeys(keyWords); + Thread.sleep(10 * 1000L); + webDriver.findElement(By.className("SearchInput--searchButton--1Sz2UIn")).click(); + Thread.sleep(30 * 1000L); + // 获取当前handler + + Set sets = webDriver.getWindowHandles(); + String newWindow = sets.stream().filter(handler -> !oldHandler.equals(handler)).findFirst().get(); + webDriver.switchTo().window(newWindow); + + List tmElementList = webDriver.findElements(By.className("product-iWrap")); + List productInfos = tmElementList.stream().map(pElement -> { + ProductInfo productInfo = new ProductInfo(); + productInfo.setDescription(pElement.findElement(By.className("productTitle")).getText()); + String price = pElement.findElement(By.className("productPrice")).getText(); + System.out.println(price); + price = price.replaceAll("¥", ""); +// productInfo.setMaxPrice(price); + return productInfo; + }).collect(Collectors.toList()); + return productInfos; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductServiceImpl.java deleted file mode 100644 index 4e72150..0000000 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductServiceImpl.java +++ /dev/null @@ -1,144 +0,0 @@ -package com.casic.missiles.modular.system.service.impl; - -import com.casic.missiles.modular.system.model.ProductInfo; -import com.casic.missiles.modular.system.service.IProductSearchService; -import lombok.SneakyThrows; -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.chrome.ChromeOptions; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; - -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -/** - * 产品搜索实例 - * - * @author lwh - */ -@Component -public class ProductServiceImpl implements IProductSearchService { - @Value("${casic.webdriver.path}") - private String path; - @Override - public List searchProducts(String type) { - //驱动地址 - String chromedriver = "D:\\dev-soft\\seleuim-chmod\\chromedriver.exe"; - System.setProperty("webdriver.chrome.driver", path); - ChromeOptions option = new ChromeOptions(); - //去掉chrome 正受到自动测试软件的控制 - option.addArguments("disable-infobars"); - //开启开发者模式 - option.setExperimentalOption("excludeSwitches", Collections.singletonList("enable-automation")); - option.addArguments("--disable-blink-features"); - option.addArguments("--disable-blink-features=AutomationControlled"); - //初始化一个chrome浏览器实例 - WebDriver webDriver = new ChromeDriver(option); - //最大化窗口 - webDriver.manage().window().maximize(); - //设置隐性等待时间 - webDriver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS); - - return searchJdProducts(webDriver); - } - - private List searchJdProducts(WebDriver webDriver) { - //打开京东地址 - webDriver.get("https://search.jd.com/Search?keyword=%E8%8B%B9%E6%9E%9C13"); - String title = webDriver.getTitle(); - List elementList = webDriver.findElements(By.className("gl-i-wrap")); - List productInfos = elementList.stream().map(webElement -> { - ProductInfo productInfo = new ProductInfo(); - productInfo.setDescription(webElement.findElement(By.className("p-name")).getText()); - productInfo.setPrice(webElement.findElement(By.className("p-price")).getText()); - return productInfo; - }).collect(Collectors.toList()); - return productInfos; - } - - @SneakyThrows - private List searchTbProducts(WebDriver webDriver) { - //打开京东地址 - webDriver.get("https://login.taobao.com/member/login.jhtml?tpl_redirect_url=https%3A%2F%2Fwww.tmall.com&style=miniall&enup=true&newMini2=true&full_redirect=true&sub=true&from=tmall&allp=assets_css%3D3.0.10/login_pc.css&pms=1650640249767"); - Thread.sleep(10 * 1000L); - - // 预登录 - webDriver.findElement(By.xpath("//input[@name='fm-login-id']")).sendKeys("18600202639"); - webDriver.findElement(By.xpath("//input[@name='fm-login-password']")).sendKeys("19881126yu"); - webDriver.findElement(By.xpath("//*[@class=\"fm-button fm-submit password-login\"]")).click(); - - String oldHandler = webDriver.getWindowHandle(); - webDriver.findElement(By.className("SearchInput--searchInputContent--1USWNEl")).sendKeys("苹果13"); - Thread.sleep(10 * 1000L); - webDriver.findElement(By.className("SearchInput--searchButton--1Sz2UIn")).click(); - Thread.sleep(30 * 1000L); - // 获取当前handler - - Set sets = webDriver.getWindowHandles(); - String newWindow = sets.stream().filter(handler -> !oldHandler.equals(handler)).findFirst().get(); - webDriver.switchTo().window(newWindow); - - List tmElementList = webDriver.findElements(By.className("product-iWrap")); - List productInfos = tmElementList.stream().map(pElement -> { - ProductInfo productInfo = new ProductInfo(); - productInfo.setDescription(pElement.findElement(By.className("productPrice")).getText()); - productInfo.setPrice(pElement.findElement(By.className("productTitle")).getText()); - return productInfo; - }).collect(Collectors.toList()); - return productInfos; - } - - public static void main(String[] args) throws InterruptedException { - //驱动地址 - String chromedriver = "D:\\dev-soft\\seleuim-chmod\\chromedriver.exe"; - System.setProperty("webdriver.chrome.driver", chromedriver); - ChromeOptions option = new ChromeOptions(); - //去掉chrome 正受到自动测试软件的控制 - option.addArguments("disable-infobars"); - //开启开发者模式 - option.setExperimentalOption("excludeSwitches", Collections.singletonList("enable-automation")); - option.addArguments("--disable-blink-features"); - option.addArguments("--disable-blink-features=AutomationControlled"); - //初始化一个chrome浏览器实例 - WebDriver webDriver = new ChromeDriver(option); - //最大化窗口 - webDriver.manage().window().maximize(); - //设置隐性等待时间 - webDriver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS); - //打开京东地址 - webDriver.get("https://login.taobao.com/member/login.jhtml?tpl_redirect_url=https%3A%2F%2Fwww.tmall.com&style=miniall&enup=true&newMini2=true&full_redirect=true&sub=true&from=tmall&allp=assets_css%3D3.0.10/login_pc.css&pms=1650640249767"); - Thread.sleep(10 * 1000L); - - // 预登录 - webDriver.findElement(By.xpath("//input[@name='fm-login-id']")).sendKeys("18600202639"); - webDriver.findElement(By.xpath("//input[@name='fm-login-password']")).sendKeys("19881126yu"); - webDriver.findElement(By.xpath("//*[@class=\"fm-button fm-submit password-login\"]")).click(); - - String oldHandler = webDriver.getWindowHandle(); - webDriver.findElement(By.className("SearchInput--searchInputContent--1USWNEl")).sendKeys("苹果13"); - Thread.sleep(10 * 1000L); - webDriver.findElement(By.className("SearchInput--searchButton--1Sz2UIn")).click(); - Thread.sleep(30 * 1000L); - // 获取当前handler - - Set sets = webDriver.getWindowHandles(); - String newWindow = sets.stream().filter(handler -> !oldHandler.equals(handler)).findFirst().get(); - webDriver.switchTo().window(newWindow); - - List tmElementList = webDriver.findElements(By.className("product-iWrap")); - List productInfos = tmElementList.stream().map(pElement -> { - ProductInfo productInfo = new ProductInfo(); - productInfo.setDescription(pElement.findElement(By.className("productPrice")).getText()); - productInfo.setPrice(pElement.findElement(By.className("productTitle")).getText()); - return productInfo; - }).collect(Collectors.toList()); - - System.out.println(productInfos); - } -} diff --git a/casic-web/pom.xml b/casic-web/pom.xml index 35f0017..eb21475 100644 --- a/casic-web/pom.xml +++ b/casic-web/pom.xml @@ -78,11 +78,6 @@ casic-admin-support ${admin.version} - - com.casic - casic-job-starter - ${extension.version} - diff --git a/casic-web/src/main/java/com/casic/missiles/ZkTest.java b/casic-web/src/main/java/com/casic/missiles/ZkTest.java deleted file mode 100644 index 7e5df40..0000000 --- a/casic-web/src/main/java/com/casic/missiles/ZkTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.casic.missiles; - -import com.casic.missiles.core.util.ZkUtil; -import org.apache.zookeeper.ZooDefs; - -public class ZkTest { - /** - * 白名单 IP添加(待增项) - * - * @param args - * @throws Exception - */ - public static void main(String[] args) throws Exception { - String zkPath = "/ss-job"; - String connectString = "localhost:2181"; - int perms = ZooDefs.Perms.ALL; - String scheme = "digest"; - String auth = "admin:Casic203"; - ZkUtil.addDigests(scheme,perms, null, connectString, zkPath); -// ZkUtil.deletePath(scheme, connectString, zkPath, auth, null); - } -} diff --git a/casic-web/src/main/resources/config/application-dev.yml b/casic-web/src/main/resources/config/application-dev.yml index d3b5903..dc2c417 100644 --- a/casic-web/src/main/resources/config/application-dev.yml +++ b/casic-web/src/main/resources/config/application-dev.yml @@ -4,7 +4,7 @@ spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://111.198.10.15:11336/casic_template2.0?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true + url: jdbc:mysql://111.198.10.15:11336/casic_reptile?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true username: root password: Casic203 jms: @@ -30,8 +30,11 @@ db: init: enable: false + tm: + account: 18600202639 + pwd: 19881126yu webdriver: - driver + path: D:\dev-soft\seleuim-chmod\chromedriver.exe logging: level.root: info level.com.casic: debug diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 0e47785..0adbba2 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -37,9 +37,19 @@ com.casic + casic-job-quartz + ${extension.version} + + + com.casic casic-selenium-core ${extension.version} + + com.google.guava + guava + 30.1-jre + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java new file mode 100644 index 0000000..9dc3950 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java @@ -0,0 +1,94 @@ +package com.casic.missiles.modular.system.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.BaseController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.system.model.ProductInfo; +import com.casic.missiles.modular.system.service.IProductInfoService; +import com.casic.missiles.modular.system.service.ISearchKeysService; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 商品信息管理控制器 + * + * @author dev + * @Date 2022-05-05 15:46:28 + */ +@Controller +@RequestMapping("/productInfo") +public class ProductInfoController extends BaseController { + @Resource + private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + + /** + * 获取商品信息管理列表 + */ + @RequestMapping(value = "/list") + @ResponseBody + public Object list(String condition) { + return productInfoService.list(null); + } + + /** + * 获取商品信息管理分页列表 + */ + @RequestMapping(value = "/listPage") + @ResponseBody + public Object listPage(String condition) { + Page page = PageFactory.defaultPage(); + QueryWrapper query = new QueryWrapper<>(); + List productInfos = productInfoService.searchDbProductPricePage(condition, page); + page.setRecords(productInfos); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 新增商品信息管理 + */ + @RequestMapping(value = "/add") + @ResponseBody + public Object add(ProductInfo productInfo) { + productInfoService.save(productInfo); + return ResponseData.success(); + } + + /** + * 删除商品信息管理 + */ + @RequestMapping(value = "/delete") + @ResponseBody + public Object delete(@RequestParam String productInfoId) { + productInfoService.removeById(productInfoId); + return ResponseData.success(); + } + + /** + * 修改商品信息管理 + */ + @RequestMapping(value = "/update") + @ResponseBody + public Object update(ProductInfo productInfo) { + productInfoService.updateById(productInfo); + return ResponseData.success(); + } + + /** + * 商品信息管理详情 + */ + @RequestMapping(value = "/detail/{productInfoId}") + @ResponseBody + public Object detail(@PathVariable("productInfoId") String productInfoId) { + return ResponseData.success(productInfoService.getById(productInfoId)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java index 78c1892..446be24 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java @@ -1,11 +1,14 @@ package com.casic.missiles.modular.system.controller; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.BaseController; import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.form.IdForms; import com.casic.missiles.model.response.ResponseData; import com.casic.missiles.modular.system.model.SearchKeys; +import com.casic.missiles.modular.system.service.IProductInfoService; import com.casic.missiles.modular.system.service.ISearchKeysService; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; @@ -24,7 +27,25 @@ @Resource private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + /** + * 获取关键字管理列表 + */ + @GetMapping(value = "/loadSearch") + @ResponseBody + public Object loadSearch(String condition) { + new Thread(){ + @Override + public void run() { + super.run(); + productInfoService.searchProducts(null); + } + }.start(); + + return ResponseData.success(); + } /** * 获取关键字管理列表 @@ -43,6 +64,10 @@ public Object listPage(String condition) { Page page = PageFactory.defaultPage(); QueryWrapper query = new QueryWrapper<>(); + if (StrUtil.isNotEmpty(condition)) { + query.like("keywords", condition); + } + page = searchKeysService.page(page, query); return ResponseData.success(super.packForBT(page)); } @@ -52,7 +77,7 @@ */ @PostMapping(value = "/add") @ResponseBody - public Object add(SearchKeys searchKeys) { + public Object add(@RequestBody SearchKeys searchKeys) { searchKeysService.save(searchKeys); return ResponseData.success(); } @@ -62,8 +87,8 @@ */ @PostMapping(value = "/delete") @ResponseBody - public Object delete(@RequestParam String searchKeysId) { - searchKeysService.removeById(searchKeysId); + public Object delete(@RequestBody IdForms searchKeysIds) { + searchKeysService.removeByIds(searchKeysIds.getIds()); return ResponseData.success(); } @@ -73,7 +98,7 @@ */ @PostMapping(value = "/update") @ResponseBody - public Object update(SearchKeys searchKeys) { + public Object update(@RequestBody SearchKeys searchKeys) { searchKeysService.updateById(searchKeys); return ResponseData.success(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java new file mode 100644 index 0000000..c3d1185 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.system.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.system.model.ProductInfo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 商品信息 Mapper 接口 + *

+ * + * @author stylefeng123 + * @since 2022-05-05 + */ +public interface ProductInfoMapper extends BaseMapper { + + /** + * 产品数据检索 + * + * @return 产品价格列表 + */ + List searchDbProductPricePage(@Param("keywords") String keywords, @Param("page") Page page); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml new file mode 100644 index 0000000..99c83ba --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + id, max_price AS maxPrice, min_price AS minPrice, description + + + + '%' || #{keywords}|| '%' + + + CONCAT('%',#{keywords},'%') + + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml index 348f2a0..4f41b58 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml @@ -5,14 +5,14 @@ - + - id, keys, search_time AS searchTime, keep_days AS keepDays + id, keywords, search_time AS searchTime, keep_days AS keepDays diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java b/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java new file mode 100644 index 0000000..df0766c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java @@ -0,0 +1,38 @@ +package com.casic.missiles.modular.system.job; + +import cn.hutool.core.util.RandomUtil; +import com.casic.missiles.modular.system.service.IProductInfoService; +import lombok.SneakyThrows; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.math.BigDecimal; + +/** + * @ClassName QuartzJob + * @Description 依赖casic-job-quartz,并在CasicApplication上增加注解 @EnableScheduling + * @Author lwh + * @Date 2021/2/5 11:20 + * @Version 1.0 + */ +@Component +public class QuartzJob { + @Resource + private IProductInfoService productInfoService; + + /** + * + */ + @SneakyThrows + @Scheduled(cron = "0 0 10,14,16 * * ?") + public void execute() { + try { + Thread.sleep(RandomUtil.randomBigDecimal(new BigDecimal(2000)).intValue()); + System.out.println("-----Thread ID 每60秒执行一次"); + productInfoService.searchProducts(null); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java index 03190bf..d5c4ecd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java @@ -1,14 +1,74 @@ package com.casic.missiles.modular.system.model; +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import com.casic.missiles.core.base.json.DateDeserializer; import lombok.Data; +import java.util.Date; + /** - * 产品信息 + *

+ * 商品信息 + *

* - * @author lenovo + * @author stylefeng123 + * @since 2022-05-05 */ @Data -public class ProductInfo { - private String description; +@TableName("reptile_product_info") +public class ProductInfo extends Model { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + private Long id; + /** + * 页面价格 + */ + @TableField("price") private String price; + /** + * 满减价格 + */ + @TableField("actual_price") + private String actualPrice; + /** + * 优惠信息 + */ + @TableField("discount") + private String discount; + + /** + * 其他信息 + */ + private String description; + + + @TableField("key_id") + private Long keyId; + + /** + * 0 页面无效 1 价格偏高 + */ + private String flag; + @JSONField(serializeUsing = DateDeserializer.class) + @TableField("create_time") + private Date createTime; + @TableField(exist = false) + private String skuName; + @TableField(exist = false) + private String skuUrl; + + @Override + public String toString() { + return "ProductInfo{" + + "id=" + id + + ", description=" + description + + "}"; + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java index 09eb7ee..ed01581 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java @@ -1,8 +1,10 @@ package com.casic.missiles.modular.system.model; +import com.alibaba.fastjson.annotation.JSONField; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.extension.activerecord.Model; +import com.casic.missiles.core.base.json.DateDeserializer; import lombok.Data; import java.util.Date; @@ -26,12 +28,24 @@ */ private Long id; /** - * 检索关键字 + * 商品名称 */ - private String keys; + @TableField("sku_name") + private String skuName; + /** + * 商品url + */ + @TableField("sku_url") + private String skuUrl; + /** + * 设定价格 + */ + @TableField("price") + private String price; /** * 最后检索时间 */ + @JSONField(serializeUsing = DateDeserializer.class) @TableField("search_time") private Date searchTime; /** @@ -40,12 +54,10 @@ @TableField("keep_days") private Integer keepDays; - @Override public String toString() { return "SearchKeys{" + "id=" + id + - ", keys=" + keys + ", searchTime=" + searchTime + ", keepDays=" + keepDays + "}"; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/service/IProductInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/system/service/IProductInfoService.java new file mode 100644 index 0000000..f6a8a35 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/service/IProductInfoService.java @@ -0,0 +1,30 @@ +package com.casic.missiles.modular.system.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.missiles.modular.system.model.ProductInfo; + +import java.util.List; + +/** + *

+ * 商品信息 服务类 + *

+ * + * @author stylefeng123 + * @since 2022-05-05 + */ +public interface IProductInfoService extends IService { + /** + * 检索商品接口定义 + * @param type jd tm + * @return + */ + public List searchProducts(String type); + /** + * 检索商品价格信息 + * @param type jd tm + * @return + */ + public List searchDbProductPricePage(String type, Page page); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductInfoServiceImpl.java new file mode 100644 index 0000000..e912cfd --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductInfoServiceImpl.java @@ -0,0 +1,218 @@ +package com.casic.missiles.modular.system.service.impl; + +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.modular.system.dao.ProductInfoMapper; +import com.casic.missiles.modular.system.model.ProductInfo; +import com.casic.missiles.modular.system.model.SearchKeys; +import com.casic.missiles.modular.system.service.IProductInfoService; +import com.casic.missiles.modular.system.service.ISearchKeysService; +import lombok.SneakyThrows; +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.chrome.ChromeDriver; +import org.openqa.selenium.chrome.ChromeOptions; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + *

+ * 商品信息 服务实现类 + *

+ * + * @author stylefeng123 + * @since 2022-05-05 + */ +@Service +public class ProductInfoServiceImpl extends ServiceImpl implements IProductInfoService { + @Value("${casic.webdriver.path}") + private String path; + @Value("${casic.tm.account}") + private String account; + @Value("${casic.tm.pwd}") + private String pwd; + @Resource + private ISearchKeysService searchKeysService; + + @Override + public List searchProducts(String type) { + System.setProperty("webdriver.chrome.driver", path); + List searchKeys = searchKeysService.list(); + Date searchTime = new Date(); + WebDriver webDriver = null; + try { + //驱动地址 + ChromeOptions option = new ChromeOptions(); + //去掉chrome 正受到自动测试软件的控制 + option.addArguments("disable-infobars"); + //开启开发者模式 + option.setExperimentalOption("excludeSwitches", Collections.singletonList("enable-automation")); + option.addArguments("--disable-blink-features"); + option.addArguments("--disable-blink-features=AutomationControlled"); + //初始化一个chrome浏览器实例 + webDriver = new ChromeDriver(option); + //最大化窗口 + webDriver.manage().window().maximize(); + //设置隐性等待时间 + webDriver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS); + for (SearchKeys searchKey : searchKeys) { +// List productInfos = searchJdProducts(webDriver, searchKey.getKeywords()); +// ProductInfo maxJd = productInfos.stream().max(Comparator.comparing(ProductInfo::getMaxPrice)).get(); +// ProductInfo minJd = productInfos.stream().min(Comparator.comparing(ProductInfo::getMaxPrice)).get(); +// // 过滤价格区间 +// ProductInfo info = new ProductInfo(); +// info.setKeyId(searchKey.getId()); +// info.setCreateTime(searchTime); +// info.setMaxPrice(maxJd.getMaxPrice()); +// info.setMinPrice(minJd.getMaxPrice()); +// StringBuilder jdStr = new StringBuilder(); +// jdStr.append("京东:").append(minJd.getDescription()).append("---").append(maxJd.getDescription()).append(" "); +// // 过滤天猫信息 +// List productTmInfos = searchTbProducts(webDriver, searchKey.getKeywords()); +// ProductInfo maxTb = productTmInfos.stream().max(Comparator.comparing(ProductInfo::getMaxPrice)).get(); +// ProductInfo minTb = productTmInfos.stream().min(Comparator.comparing(ProductInfo::getMaxPrice)).get(); +// info.setMaxTmPrice(maxTb.getMaxPrice()); +// info.setMinTmPrice(minTb.getMaxPrice()); +// jdStr.append("天猫:").append(minTb.getDescription()).append("---").append(maxTb.getDescription()).append(" "); + +// info.setDescription(jdStr.toString()); +// this.save(info); + searchKey.setSearchTime(searchTime); + searchKeysService.updateById(searchKey); + } + + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (webDriver != null) { + webDriver.close(); + webDriver.quit(); + } + } + return new ArrayList<>(); + } + + @Override + public List searchDbProductPricePage(String keywords, Page page) { + return this.baseMapper.searchDbProductPricePage(keywords, page); + } + + private ProductInfo searchJdDetail(WebDriver webDriver, String url) { + ProductInfo productInfo = new ProductInfo(); + //打开京东地址 + webDriver.get(url); + String title = webDriver.getTitle(); + WebElement skuEl = webDriver.findElement(By.className("sku-name")); + if (skuEl != null) { + String skuName = skuEl.getText(); + productInfo.setDescription(skuName); + } else { + productInfo.setFlag("1"); + } + + // NO1 读取价格信息 + WebElement priceEl = webDriver.findElement(By.className("p-price")); + if (priceEl != null) { + WebElement webP = priceEl.findElement(By.className("price")); + if (webP != null && NumberUtil.isNumber(webP.getText())) { + //设置页面价格 + productInfo.setPrice(webP.getText()); + } else { + //页面元素获取异常 判定为页面失效 + productInfo.setFlag("1"); + } + } else { + //页面元素获取异常 判定为页面失效 + productInfo.setFlag("1"); + } + + // NO2 读取打折信息 + WebElement promItem = webDriver.findElement(By.className("prom-item")); + if (promItem != null) { + //提取满减信息 + WebElement redElm = promItem.findElement(By.className("hl_red")); + String text = redElm.getText(); + if (StrUtil.isNotEmpty(text)) { + //提取满减 + String bg = promItem.findElement(By.className("hl_red_bg")).getText(); + String reg = "[\\u4E00-\\u9FA5]+"; + List list = Stream.of(reg.split(reg)).filter(StrUtil::isNotEmpty).collect(Collectors.toList()); + if (list.size() > 0 && list.stream().anyMatch(NumberUtil::isNumber)) { + //计算满减价格 + //判断价格是否符合满减数 + if ("满减".equals(bg) && list.size() > 2) { + BigDecimal skuPrice = NumberUtil.toBigDecimal(productInfo.getPrice()); + if (skuPrice.compareTo(NumberUtil.toBigDecimal(list.get(0))) >= 0) { + BigDecimal discountPrice = NumberUtil.toBigDecimal(list.get(1)); + //设置实际价格 + productInfo.setActualPrice(skuPrice.subtract(discountPrice).toString()); + } + } + } + } + } + + return productInfo; + } + + private List searchJdProducts(WebDriver webDriver, String keywords) { + //打开京东地址 + webDriver.get("https://search.jd.com/Search?keyword=" + keywords); + String title = webDriver.getTitle(); + List elementList = webDriver.findElements(By.className("gl-i-wrap")); + List productInfos = elementList.stream().map(webElement -> { + ProductInfo productInfo = new ProductInfo(); + productInfo.setDescription(webElement.findElement(By.className("p-name")).getText()); + String price = webElement.findElement(By.className("p-price")).getText(); + price = price.replaceAll("¥", ""); +// productInfo.setMaxPrice(price); + return productInfo; + }).collect(Collectors.toList()); + return productInfos; + } + + @SneakyThrows + private List searchTbProducts(WebDriver webDriver, String keyWords) { + //打开京东地址 + webDriver.get("https://login.taobao.com/member/login.jhtml?tpl_redirect_url=https%3A%2F%2Fwww.tmall.com&style=miniall&enup=true&newMini2=true&full_redirect=true&sub=true&from=tmall&allp=assets_css%3D3.0.10/login_pc.css&pms=1650640249767"); + Thread.sleep(10 * 1000L); + + // 预登录 + webDriver.findElement(By.xpath("//input[@name='fm-login-id']")).sendKeys(account); + webDriver.findElement(By.xpath("//input[@name='fm-login-password']")).sendKeys(pwd); + webDriver.findElement(By.xpath("//*[@class=\"fm-button fm-submit password-login\"]")).click(); + + String oldHandler = webDriver.getWindowHandle(); + webDriver.findElement(By.className("SearchInput--searchInputContent--1USWNEl")).sendKeys(keyWords); + Thread.sleep(10 * 1000L); + webDriver.findElement(By.className("SearchInput--searchButton--1Sz2UIn")).click(); + Thread.sleep(30 * 1000L); + // 获取当前handler + + Set sets = webDriver.getWindowHandles(); + String newWindow = sets.stream().filter(handler -> !oldHandler.equals(handler)).findFirst().get(); + webDriver.switchTo().window(newWindow); + + List tmElementList = webDriver.findElements(By.className("product-iWrap")); + List productInfos = tmElementList.stream().map(pElement -> { + ProductInfo productInfo = new ProductInfo(); + productInfo.setDescription(pElement.findElement(By.className("productTitle")).getText()); + String price = pElement.findElement(By.className("productPrice")).getText(); + System.out.println(price); + price = price.replaceAll("¥", ""); +// productInfo.setMaxPrice(price); + return productInfo; + }).collect(Collectors.toList()); + return productInfos; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductServiceImpl.java deleted file mode 100644 index 4e72150..0000000 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductServiceImpl.java +++ /dev/null @@ -1,144 +0,0 @@ -package com.casic.missiles.modular.system.service.impl; - -import com.casic.missiles.modular.system.model.ProductInfo; -import com.casic.missiles.modular.system.service.IProductSearchService; -import lombok.SneakyThrows; -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.chrome.ChromeOptions; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; - -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -/** - * 产品搜索实例 - * - * @author lwh - */ -@Component -public class ProductServiceImpl implements IProductSearchService { - @Value("${casic.webdriver.path}") - private String path; - @Override - public List searchProducts(String type) { - //驱动地址 - String chromedriver = "D:\\dev-soft\\seleuim-chmod\\chromedriver.exe"; - System.setProperty("webdriver.chrome.driver", path); - ChromeOptions option = new ChromeOptions(); - //去掉chrome 正受到自动测试软件的控制 - option.addArguments("disable-infobars"); - //开启开发者模式 - option.setExperimentalOption("excludeSwitches", Collections.singletonList("enable-automation")); - option.addArguments("--disable-blink-features"); - option.addArguments("--disable-blink-features=AutomationControlled"); - //初始化一个chrome浏览器实例 - WebDriver webDriver = new ChromeDriver(option); - //最大化窗口 - webDriver.manage().window().maximize(); - //设置隐性等待时间 - webDriver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS); - - return searchJdProducts(webDriver); - } - - private List searchJdProducts(WebDriver webDriver) { - //打开京东地址 - webDriver.get("https://search.jd.com/Search?keyword=%E8%8B%B9%E6%9E%9C13"); - String title = webDriver.getTitle(); - List elementList = webDriver.findElements(By.className("gl-i-wrap")); - List productInfos = elementList.stream().map(webElement -> { - ProductInfo productInfo = new ProductInfo(); - productInfo.setDescription(webElement.findElement(By.className("p-name")).getText()); - productInfo.setPrice(webElement.findElement(By.className("p-price")).getText()); - return productInfo; - }).collect(Collectors.toList()); - return productInfos; - } - - @SneakyThrows - private List searchTbProducts(WebDriver webDriver) { - //打开京东地址 - webDriver.get("https://login.taobao.com/member/login.jhtml?tpl_redirect_url=https%3A%2F%2Fwww.tmall.com&style=miniall&enup=true&newMini2=true&full_redirect=true&sub=true&from=tmall&allp=assets_css%3D3.0.10/login_pc.css&pms=1650640249767"); - Thread.sleep(10 * 1000L); - - // 预登录 - webDriver.findElement(By.xpath("//input[@name='fm-login-id']")).sendKeys("18600202639"); - webDriver.findElement(By.xpath("//input[@name='fm-login-password']")).sendKeys("19881126yu"); - webDriver.findElement(By.xpath("//*[@class=\"fm-button fm-submit password-login\"]")).click(); - - String oldHandler = webDriver.getWindowHandle(); - webDriver.findElement(By.className("SearchInput--searchInputContent--1USWNEl")).sendKeys("苹果13"); - Thread.sleep(10 * 1000L); - webDriver.findElement(By.className("SearchInput--searchButton--1Sz2UIn")).click(); - Thread.sleep(30 * 1000L); - // 获取当前handler - - Set sets = webDriver.getWindowHandles(); - String newWindow = sets.stream().filter(handler -> !oldHandler.equals(handler)).findFirst().get(); - webDriver.switchTo().window(newWindow); - - List tmElementList = webDriver.findElements(By.className("product-iWrap")); - List productInfos = tmElementList.stream().map(pElement -> { - ProductInfo productInfo = new ProductInfo(); - productInfo.setDescription(pElement.findElement(By.className("productPrice")).getText()); - productInfo.setPrice(pElement.findElement(By.className("productTitle")).getText()); - return productInfo; - }).collect(Collectors.toList()); - return productInfos; - } - - public static void main(String[] args) throws InterruptedException { - //驱动地址 - String chromedriver = "D:\\dev-soft\\seleuim-chmod\\chromedriver.exe"; - System.setProperty("webdriver.chrome.driver", chromedriver); - ChromeOptions option = new ChromeOptions(); - //去掉chrome 正受到自动测试软件的控制 - option.addArguments("disable-infobars"); - //开启开发者模式 - option.setExperimentalOption("excludeSwitches", Collections.singletonList("enable-automation")); - option.addArguments("--disable-blink-features"); - option.addArguments("--disable-blink-features=AutomationControlled"); - //初始化一个chrome浏览器实例 - WebDriver webDriver = new ChromeDriver(option); - //最大化窗口 - webDriver.manage().window().maximize(); - //设置隐性等待时间 - webDriver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS); - //打开京东地址 - webDriver.get("https://login.taobao.com/member/login.jhtml?tpl_redirect_url=https%3A%2F%2Fwww.tmall.com&style=miniall&enup=true&newMini2=true&full_redirect=true&sub=true&from=tmall&allp=assets_css%3D3.0.10/login_pc.css&pms=1650640249767"); - Thread.sleep(10 * 1000L); - - // 预登录 - webDriver.findElement(By.xpath("//input[@name='fm-login-id']")).sendKeys("18600202639"); - webDriver.findElement(By.xpath("//input[@name='fm-login-password']")).sendKeys("19881126yu"); - webDriver.findElement(By.xpath("//*[@class=\"fm-button fm-submit password-login\"]")).click(); - - String oldHandler = webDriver.getWindowHandle(); - webDriver.findElement(By.className("SearchInput--searchInputContent--1USWNEl")).sendKeys("苹果13"); - Thread.sleep(10 * 1000L); - webDriver.findElement(By.className("SearchInput--searchButton--1Sz2UIn")).click(); - Thread.sleep(30 * 1000L); - // 获取当前handler - - Set sets = webDriver.getWindowHandles(); - String newWindow = sets.stream().filter(handler -> !oldHandler.equals(handler)).findFirst().get(); - webDriver.switchTo().window(newWindow); - - List tmElementList = webDriver.findElements(By.className("product-iWrap")); - List productInfos = tmElementList.stream().map(pElement -> { - ProductInfo productInfo = new ProductInfo(); - productInfo.setDescription(pElement.findElement(By.className("productPrice")).getText()); - productInfo.setPrice(pElement.findElement(By.className("productTitle")).getText()); - return productInfo; - }).collect(Collectors.toList()); - - System.out.println(productInfos); - } -} diff --git a/casic-web/pom.xml b/casic-web/pom.xml index 35f0017..eb21475 100644 --- a/casic-web/pom.xml +++ b/casic-web/pom.xml @@ -78,11 +78,6 @@ casic-admin-support ${admin.version} - - com.casic - casic-job-starter - ${extension.version} - diff --git a/casic-web/src/main/java/com/casic/missiles/ZkTest.java b/casic-web/src/main/java/com/casic/missiles/ZkTest.java deleted file mode 100644 index 7e5df40..0000000 --- a/casic-web/src/main/java/com/casic/missiles/ZkTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.casic.missiles; - -import com.casic.missiles.core.util.ZkUtil; -import org.apache.zookeeper.ZooDefs; - -public class ZkTest { - /** - * 白名单 IP添加(待增项) - * - * @param args - * @throws Exception - */ - public static void main(String[] args) throws Exception { - String zkPath = "/ss-job"; - String connectString = "localhost:2181"; - int perms = ZooDefs.Perms.ALL; - String scheme = "digest"; - String auth = "admin:Casic203"; - ZkUtil.addDigests(scheme,perms, null, connectString, zkPath); -// ZkUtil.deletePath(scheme, connectString, zkPath, auth, null); - } -} diff --git a/casic-web/src/main/resources/config/application-dev.yml b/casic-web/src/main/resources/config/application-dev.yml index d3b5903..dc2c417 100644 --- a/casic-web/src/main/resources/config/application-dev.yml +++ b/casic-web/src/main/resources/config/application-dev.yml @@ -4,7 +4,7 @@ spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://111.198.10.15:11336/casic_template2.0?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true + url: jdbc:mysql://111.198.10.15:11336/casic_reptile?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true username: root password: Casic203 jms: @@ -30,8 +30,11 @@ db: init: enable: false + tm: + account: 18600202639 + pwd: 19881126yu webdriver: - driver + path: D:\dev-soft\seleuim-chmod\chromedriver.exe logging: level.root: info level.com.casic: debug diff --git a/casic-web/src/main/resources/config/application-nacos.yml b/casic-web/src/main/resources/config/application-nacos.yml deleted file mode 100644 index 674a98f..0000000 --- a/casic-web/src/main/resources/config/application-nacos.yml +++ /dev/null @@ -1,13 +0,0 @@ -nacos: - # endpoint http://localhost:8080/actuator/nacos-config - # health http://localhost:8080/actuator/health - config: - server-addr: 127.0.0.1:8848 -management: -# endpoints: -# web: -# exposure: -# include: * - endpoint: - health: - show-details: always \ No newline at end of file diff --git a/casic-server/pom.xml b/casic-server/pom.xml index 0e47785..0adbba2 100644 --- a/casic-server/pom.xml +++ b/casic-server/pom.xml @@ -37,9 +37,19 @@ com.casic + casic-job-quartz + ${extension.version} + + + com.casic casic-selenium-core ${extension.version} + + com.google.guava + guava + 30.1-jre + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java new file mode 100644 index 0000000..9dc3950 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/ProductInfoController.java @@ -0,0 +1,94 @@ +package com.casic.missiles.modular.system.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.core.base.controller.BaseController; +import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.response.ResponseData; +import com.casic.missiles.modular.system.model.ProductInfo; +import com.casic.missiles.modular.system.service.IProductInfoService; +import com.casic.missiles.modular.system.service.ISearchKeysService; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 商品信息管理控制器 + * + * @author dev + * @Date 2022-05-05 15:46:28 + */ +@Controller +@RequestMapping("/productInfo") +public class ProductInfoController extends BaseController { + @Resource + private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + + /** + * 获取商品信息管理列表 + */ + @RequestMapping(value = "/list") + @ResponseBody + public Object list(String condition) { + return productInfoService.list(null); + } + + /** + * 获取商品信息管理分页列表 + */ + @RequestMapping(value = "/listPage") + @ResponseBody + public Object listPage(String condition) { + Page page = PageFactory.defaultPage(); + QueryWrapper query = new QueryWrapper<>(); + List productInfos = productInfoService.searchDbProductPricePage(condition, page); + page.setRecords(productInfos); + return ResponseData.success(super.packForBT(page)); + } + + /** + * 新增商品信息管理 + */ + @RequestMapping(value = "/add") + @ResponseBody + public Object add(ProductInfo productInfo) { + productInfoService.save(productInfo); + return ResponseData.success(); + } + + /** + * 删除商品信息管理 + */ + @RequestMapping(value = "/delete") + @ResponseBody + public Object delete(@RequestParam String productInfoId) { + productInfoService.removeById(productInfoId); + return ResponseData.success(); + } + + /** + * 修改商品信息管理 + */ + @RequestMapping(value = "/update") + @ResponseBody + public Object update(ProductInfo productInfo) { + productInfoService.updateById(productInfo); + return ResponseData.success(); + } + + /** + * 商品信息管理详情 + */ + @RequestMapping(value = "/detail/{productInfoId}") + @ResponseBody + public Object detail(@PathVariable("productInfoId") String productInfoId) { + return ResponseData.success(productInfoService.getById(productInfoId)); + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java index 78c1892..446be24 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/controller/SearchKeysController.java @@ -1,11 +1,14 @@ package com.casic.missiles.modular.system.controller; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.BaseController; import com.casic.missiles.core.page.PageFactory; +import com.casic.missiles.model.form.IdForms; import com.casic.missiles.model.response.ResponseData; import com.casic.missiles.modular.system.model.SearchKeys; +import com.casic.missiles.modular.system.service.IProductInfoService; import com.casic.missiles.modular.system.service.ISearchKeysService; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; @@ -24,7 +27,25 @@ @Resource private ISearchKeysService searchKeysService; + @Resource + private IProductInfoService productInfoService; + /** + * 获取关键字管理列表 + */ + @GetMapping(value = "/loadSearch") + @ResponseBody + public Object loadSearch(String condition) { + new Thread(){ + @Override + public void run() { + super.run(); + productInfoService.searchProducts(null); + } + }.start(); + + return ResponseData.success(); + } /** * 获取关键字管理列表 @@ -43,6 +64,10 @@ public Object listPage(String condition) { Page page = PageFactory.defaultPage(); QueryWrapper query = new QueryWrapper<>(); + if (StrUtil.isNotEmpty(condition)) { + query.like("keywords", condition); + } + page = searchKeysService.page(page, query); return ResponseData.success(super.packForBT(page)); } @@ -52,7 +77,7 @@ */ @PostMapping(value = "/add") @ResponseBody - public Object add(SearchKeys searchKeys) { + public Object add(@RequestBody SearchKeys searchKeys) { searchKeysService.save(searchKeys); return ResponseData.success(); } @@ -62,8 +87,8 @@ */ @PostMapping(value = "/delete") @ResponseBody - public Object delete(@RequestParam String searchKeysId) { - searchKeysService.removeById(searchKeysId); + public Object delete(@RequestBody IdForms searchKeysIds) { + searchKeysService.removeByIds(searchKeysIds.getIds()); return ResponseData.success(); } @@ -73,7 +98,7 @@ */ @PostMapping(value = "/update") @ResponseBody - public Object update(SearchKeys searchKeys) { + public Object update(@RequestBody SearchKeys searchKeys) { searchKeysService.updateById(searchKeys); return ResponseData.success(); } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java new file mode 100644 index 0000000..c3d1185 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/ProductInfoMapper.java @@ -0,0 +1,26 @@ +package com.casic.missiles.modular.system.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.modular.system.model.ProductInfo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 商品信息 Mapper 接口 + *

+ * + * @author stylefeng123 + * @since 2022-05-05 + */ +public interface ProductInfoMapper extends BaseMapper { + + /** + * 产品数据检索 + * + * @return 产品价格列表 + */ + List searchDbProductPricePage(@Param("keywords") String keywords, @Param("page") Page page); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml new file mode 100644 index 0000000..99c83ba --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/ProductInfoMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + id, max_price AS maxPrice, min_price AS minPrice, description + + + + '%' || #{keywords}|| '%' + + + CONCAT('%',#{keywords},'%') + + diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml index 348f2a0..4f41b58 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/dao/mapping/SearchKeysMapper.xml @@ -5,14 +5,14 @@ - + - id, keys, search_time AS searchTime, keep_days AS keepDays + id, keywords, search_time AS searchTime, keep_days AS keepDays diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java b/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java new file mode 100644 index 0000000..df0766c --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/job/QuartzJob.java @@ -0,0 +1,38 @@ +package com.casic.missiles.modular.system.job; + +import cn.hutool.core.util.RandomUtil; +import com.casic.missiles.modular.system.service.IProductInfoService; +import lombok.SneakyThrows; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.math.BigDecimal; + +/** + * @ClassName QuartzJob + * @Description 依赖casic-job-quartz,并在CasicApplication上增加注解 @EnableScheduling + * @Author lwh + * @Date 2021/2/5 11:20 + * @Version 1.0 + */ +@Component +public class QuartzJob { + @Resource + private IProductInfoService productInfoService; + + /** + * + */ + @SneakyThrows + @Scheduled(cron = "0 0 10,14,16 * * ?") + public void execute() { + try { + Thread.sleep(RandomUtil.randomBigDecimal(new BigDecimal(2000)).intValue()); + System.out.println("-----Thread ID 每60秒执行一次"); + productInfoService.searchProducts(null); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java b/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java index 03190bf..d5c4ecd 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/model/ProductInfo.java @@ -1,14 +1,74 @@ package com.casic.missiles.modular.system.model; +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import com.casic.missiles.core.base.json.DateDeserializer; import lombok.Data; +import java.util.Date; + /** - * 产品信息 + *

+ * 商品信息 + *

* - * @author lenovo + * @author stylefeng123 + * @since 2022-05-05 */ @Data -public class ProductInfo { - private String description; +@TableName("reptile_product_info") +public class ProductInfo extends Model { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + private Long id; + /** + * 页面价格 + */ + @TableField("price") private String price; + /** + * 满减价格 + */ + @TableField("actual_price") + private String actualPrice; + /** + * 优惠信息 + */ + @TableField("discount") + private String discount; + + /** + * 其他信息 + */ + private String description; + + + @TableField("key_id") + private Long keyId; + + /** + * 0 页面无效 1 价格偏高 + */ + private String flag; + @JSONField(serializeUsing = DateDeserializer.class) + @TableField("create_time") + private Date createTime; + @TableField(exist = false) + private String skuName; + @TableField(exist = false) + private String skuUrl; + + @Override + public String toString() { + return "ProductInfo{" + + "id=" + id + + ", description=" + description + + "}"; + } } diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java b/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java index 09eb7ee..ed01581 100644 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/model/SearchKeys.java @@ -1,8 +1,10 @@ package com.casic.missiles.modular.system.model; +import com.alibaba.fastjson.annotation.JSONField; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.extension.activerecord.Model; +import com.casic.missiles.core.base.json.DateDeserializer; import lombok.Data; import java.util.Date; @@ -26,12 +28,24 @@ */ private Long id; /** - * 检索关键字 + * 商品名称 */ - private String keys; + @TableField("sku_name") + private String skuName; + /** + * 商品url + */ + @TableField("sku_url") + private String skuUrl; + /** + * 设定价格 + */ + @TableField("price") + private String price; /** * 最后检索时间 */ + @JSONField(serializeUsing = DateDeserializer.class) @TableField("search_time") private Date searchTime; /** @@ -40,12 +54,10 @@ @TableField("keep_days") private Integer keepDays; - @Override public String toString() { return "SearchKeys{" + "id=" + id + - ", keys=" + keys + ", searchTime=" + searchTime + ", keepDays=" + keepDays + "}"; diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/service/IProductInfoService.java b/casic-server/src/main/java/com/casic/missiles/modular/system/service/IProductInfoService.java new file mode 100644 index 0000000..f6a8a35 --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/service/IProductInfoService.java @@ -0,0 +1,30 @@ +package com.casic.missiles.modular.system.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.casic.missiles.modular.system.model.ProductInfo; + +import java.util.List; + +/** + *

+ * 商品信息 服务类 + *

+ * + * @author stylefeng123 + * @since 2022-05-05 + */ +public interface IProductInfoService extends IService { + /** + * 检索商品接口定义 + * @param type jd tm + * @return + */ + public List searchProducts(String type); + /** + * 检索商品价格信息 + * @param type jd tm + * @return + */ + public List searchDbProductPricePage(String type, Page page); +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductInfoServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductInfoServiceImpl.java new file mode 100644 index 0000000..e912cfd --- /dev/null +++ b/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductInfoServiceImpl.java @@ -0,0 +1,218 @@ +package com.casic.missiles.modular.system.service.impl; + +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.modular.system.dao.ProductInfoMapper; +import com.casic.missiles.modular.system.model.ProductInfo; +import com.casic.missiles.modular.system.model.SearchKeys; +import com.casic.missiles.modular.system.service.IProductInfoService; +import com.casic.missiles.modular.system.service.ISearchKeysService; +import lombok.SneakyThrows; +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.chrome.ChromeDriver; +import org.openqa.selenium.chrome.ChromeOptions; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + *

+ * 商品信息 服务实现类 + *

+ * + * @author stylefeng123 + * @since 2022-05-05 + */ +@Service +public class ProductInfoServiceImpl extends ServiceImpl implements IProductInfoService { + @Value("${casic.webdriver.path}") + private String path; + @Value("${casic.tm.account}") + private String account; + @Value("${casic.tm.pwd}") + private String pwd; + @Resource + private ISearchKeysService searchKeysService; + + @Override + public List searchProducts(String type) { + System.setProperty("webdriver.chrome.driver", path); + List searchKeys = searchKeysService.list(); + Date searchTime = new Date(); + WebDriver webDriver = null; + try { + //驱动地址 + ChromeOptions option = new ChromeOptions(); + //去掉chrome 正受到自动测试软件的控制 + option.addArguments("disable-infobars"); + //开启开发者模式 + option.setExperimentalOption("excludeSwitches", Collections.singletonList("enable-automation")); + option.addArguments("--disable-blink-features"); + option.addArguments("--disable-blink-features=AutomationControlled"); + //初始化一个chrome浏览器实例 + webDriver = new ChromeDriver(option); + //最大化窗口 + webDriver.manage().window().maximize(); + //设置隐性等待时间 + webDriver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS); + for (SearchKeys searchKey : searchKeys) { +// List productInfos = searchJdProducts(webDriver, searchKey.getKeywords()); +// ProductInfo maxJd = productInfos.stream().max(Comparator.comparing(ProductInfo::getMaxPrice)).get(); +// ProductInfo minJd = productInfos.stream().min(Comparator.comparing(ProductInfo::getMaxPrice)).get(); +// // 过滤价格区间 +// ProductInfo info = new ProductInfo(); +// info.setKeyId(searchKey.getId()); +// info.setCreateTime(searchTime); +// info.setMaxPrice(maxJd.getMaxPrice()); +// info.setMinPrice(minJd.getMaxPrice()); +// StringBuilder jdStr = new StringBuilder(); +// jdStr.append("京东:").append(minJd.getDescription()).append("---").append(maxJd.getDescription()).append(" "); +// // 过滤天猫信息 +// List productTmInfos = searchTbProducts(webDriver, searchKey.getKeywords()); +// ProductInfo maxTb = productTmInfos.stream().max(Comparator.comparing(ProductInfo::getMaxPrice)).get(); +// ProductInfo minTb = productTmInfos.stream().min(Comparator.comparing(ProductInfo::getMaxPrice)).get(); +// info.setMaxTmPrice(maxTb.getMaxPrice()); +// info.setMinTmPrice(minTb.getMaxPrice()); +// jdStr.append("天猫:").append(minTb.getDescription()).append("---").append(maxTb.getDescription()).append(" "); + +// info.setDescription(jdStr.toString()); +// this.save(info); + searchKey.setSearchTime(searchTime); + searchKeysService.updateById(searchKey); + } + + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (webDriver != null) { + webDriver.close(); + webDriver.quit(); + } + } + return new ArrayList<>(); + } + + @Override + public List searchDbProductPricePage(String keywords, Page page) { + return this.baseMapper.searchDbProductPricePage(keywords, page); + } + + private ProductInfo searchJdDetail(WebDriver webDriver, String url) { + ProductInfo productInfo = new ProductInfo(); + //打开京东地址 + webDriver.get(url); + String title = webDriver.getTitle(); + WebElement skuEl = webDriver.findElement(By.className("sku-name")); + if (skuEl != null) { + String skuName = skuEl.getText(); + productInfo.setDescription(skuName); + } else { + productInfo.setFlag("1"); + } + + // NO1 读取价格信息 + WebElement priceEl = webDriver.findElement(By.className("p-price")); + if (priceEl != null) { + WebElement webP = priceEl.findElement(By.className("price")); + if (webP != null && NumberUtil.isNumber(webP.getText())) { + //设置页面价格 + productInfo.setPrice(webP.getText()); + } else { + //页面元素获取异常 判定为页面失效 + productInfo.setFlag("1"); + } + } else { + //页面元素获取异常 判定为页面失效 + productInfo.setFlag("1"); + } + + // NO2 读取打折信息 + WebElement promItem = webDriver.findElement(By.className("prom-item")); + if (promItem != null) { + //提取满减信息 + WebElement redElm = promItem.findElement(By.className("hl_red")); + String text = redElm.getText(); + if (StrUtil.isNotEmpty(text)) { + //提取满减 + String bg = promItem.findElement(By.className("hl_red_bg")).getText(); + String reg = "[\\u4E00-\\u9FA5]+"; + List list = Stream.of(reg.split(reg)).filter(StrUtil::isNotEmpty).collect(Collectors.toList()); + if (list.size() > 0 && list.stream().anyMatch(NumberUtil::isNumber)) { + //计算满减价格 + //判断价格是否符合满减数 + if ("满减".equals(bg) && list.size() > 2) { + BigDecimal skuPrice = NumberUtil.toBigDecimal(productInfo.getPrice()); + if (skuPrice.compareTo(NumberUtil.toBigDecimal(list.get(0))) >= 0) { + BigDecimal discountPrice = NumberUtil.toBigDecimal(list.get(1)); + //设置实际价格 + productInfo.setActualPrice(skuPrice.subtract(discountPrice).toString()); + } + } + } + } + } + + return productInfo; + } + + private List searchJdProducts(WebDriver webDriver, String keywords) { + //打开京东地址 + webDriver.get("https://search.jd.com/Search?keyword=" + keywords); + String title = webDriver.getTitle(); + List elementList = webDriver.findElements(By.className("gl-i-wrap")); + List productInfos = elementList.stream().map(webElement -> { + ProductInfo productInfo = new ProductInfo(); + productInfo.setDescription(webElement.findElement(By.className("p-name")).getText()); + String price = webElement.findElement(By.className("p-price")).getText(); + price = price.replaceAll("¥", ""); +// productInfo.setMaxPrice(price); + return productInfo; + }).collect(Collectors.toList()); + return productInfos; + } + + @SneakyThrows + private List searchTbProducts(WebDriver webDriver, String keyWords) { + //打开京东地址 + webDriver.get("https://login.taobao.com/member/login.jhtml?tpl_redirect_url=https%3A%2F%2Fwww.tmall.com&style=miniall&enup=true&newMini2=true&full_redirect=true&sub=true&from=tmall&allp=assets_css%3D3.0.10/login_pc.css&pms=1650640249767"); + Thread.sleep(10 * 1000L); + + // 预登录 + webDriver.findElement(By.xpath("//input[@name='fm-login-id']")).sendKeys(account); + webDriver.findElement(By.xpath("//input[@name='fm-login-password']")).sendKeys(pwd); + webDriver.findElement(By.xpath("//*[@class=\"fm-button fm-submit password-login\"]")).click(); + + String oldHandler = webDriver.getWindowHandle(); + webDriver.findElement(By.className("SearchInput--searchInputContent--1USWNEl")).sendKeys(keyWords); + Thread.sleep(10 * 1000L); + webDriver.findElement(By.className("SearchInput--searchButton--1Sz2UIn")).click(); + Thread.sleep(30 * 1000L); + // 获取当前handler + + Set sets = webDriver.getWindowHandles(); + String newWindow = sets.stream().filter(handler -> !oldHandler.equals(handler)).findFirst().get(); + webDriver.switchTo().window(newWindow); + + List tmElementList = webDriver.findElements(By.className("product-iWrap")); + List productInfos = tmElementList.stream().map(pElement -> { + ProductInfo productInfo = new ProductInfo(); + productInfo.setDescription(pElement.findElement(By.className("productTitle")).getText()); + String price = pElement.findElement(By.className("productPrice")).getText(); + System.out.println(price); + price = price.replaceAll("¥", ""); +// productInfo.setMaxPrice(price); + return productInfo; + }).collect(Collectors.toList()); + return productInfos; + } +} diff --git a/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductServiceImpl.java b/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductServiceImpl.java deleted file mode 100644 index 4e72150..0000000 --- a/casic-server/src/main/java/com/casic/missiles/modular/system/service/impl/ProductServiceImpl.java +++ /dev/null @@ -1,144 +0,0 @@ -package com.casic.missiles.modular.system.service.impl; - -import com.casic.missiles.modular.system.model.ProductInfo; -import com.casic.missiles.modular.system.service.IProductSearchService; -import lombok.SneakyThrows; -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.chrome.ChromeOptions; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; - -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -/** - * 产品搜索实例 - * - * @author lwh - */ -@Component -public class ProductServiceImpl implements IProductSearchService { - @Value("${casic.webdriver.path}") - private String path; - @Override - public List searchProducts(String type) { - //驱动地址 - String chromedriver = "D:\\dev-soft\\seleuim-chmod\\chromedriver.exe"; - System.setProperty("webdriver.chrome.driver", path); - ChromeOptions option = new ChromeOptions(); - //去掉chrome 正受到自动测试软件的控制 - option.addArguments("disable-infobars"); - //开启开发者模式 - option.setExperimentalOption("excludeSwitches", Collections.singletonList("enable-automation")); - option.addArguments("--disable-blink-features"); - option.addArguments("--disable-blink-features=AutomationControlled"); - //初始化一个chrome浏览器实例 - WebDriver webDriver = new ChromeDriver(option); - //最大化窗口 - webDriver.manage().window().maximize(); - //设置隐性等待时间 - webDriver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS); - - return searchJdProducts(webDriver); - } - - private List searchJdProducts(WebDriver webDriver) { - //打开京东地址 - webDriver.get("https://search.jd.com/Search?keyword=%E8%8B%B9%E6%9E%9C13"); - String title = webDriver.getTitle(); - List elementList = webDriver.findElements(By.className("gl-i-wrap")); - List productInfos = elementList.stream().map(webElement -> { - ProductInfo productInfo = new ProductInfo(); - productInfo.setDescription(webElement.findElement(By.className("p-name")).getText()); - productInfo.setPrice(webElement.findElement(By.className("p-price")).getText()); - return productInfo; - }).collect(Collectors.toList()); - return productInfos; - } - - @SneakyThrows - private List searchTbProducts(WebDriver webDriver) { - //打开京东地址 - webDriver.get("https://login.taobao.com/member/login.jhtml?tpl_redirect_url=https%3A%2F%2Fwww.tmall.com&style=miniall&enup=true&newMini2=true&full_redirect=true&sub=true&from=tmall&allp=assets_css%3D3.0.10/login_pc.css&pms=1650640249767"); - Thread.sleep(10 * 1000L); - - // 预登录 - webDriver.findElement(By.xpath("//input[@name='fm-login-id']")).sendKeys("18600202639"); - webDriver.findElement(By.xpath("//input[@name='fm-login-password']")).sendKeys("19881126yu"); - webDriver.findElement(By.xpath("//*[@class=\"fm-button fm-submit password-login\"]")).click(); - - String oldHandler = webDriver.getWindowHandle(); - webDriver.findElement(By.className("SearchInput--searchInputContent--1USWNEl")).sendKeys("苹果13"); - Thread.sleep(10 * 1000L); - webDriver.findElement(By.className("SearchInput--searchButton--1Sz2UIn")).click(); - Thread.sleep(30 * 1000L); - // 获取当前handler - - Set sets = webDriver.getWindowHandles(); - String newWindow = sets.stream().filter(handler -> !oldHandler.equals(handler)).findFirst().get(); - webDriver.switchTo().window(newWindow); - - List tmElementList = webDriver.findElements(By.className("product-iWrap")); - List productInfos = tmElementList.stream().map(pElement -> { - ProductInfo productInfo = new ProductInfo(); - productInfo.setDescription(pElement.findElement(By.className("productPrice")).getText()); - productInfo.setPrice(pElement.findElement(By.className("productTitle")).getText()); - return productInfo; - }).collect(Collectors.toList()); - return productInfos; - } - - public static void main(String[] args) throws InterruptedException { - //驱动地址 - String chromedriver = "D:\\dev-soft\\seleuim-chmod\\chromedriver.exe"; - System.setProperty("webdriver.chrome.driver", chromedriver); - ChromeOptions option = new ChromeOptions(); - //去掉chrome 正受到自动测试软件的控制 - option.addArguments("disable-infobars"); - //开启开发者模式 - option.setExperimentalOption("excludeSwitches", Collections.singletonList("enable-automation")); - option.addArguments("--disable-blink-features"); - option.addArguments("--disable-blink-features=AutomationControlled"); - //初始化一个chrome浏览器实例 - WebDriver webDriver = new ChromeDriver(option); - //最大化窗口 - webDriver.manage().window().maximize(); - //设置隐性等待时间 - webDriver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS); - //打开京东地址 - webDriver.get("https://login.taobao.com/member/login.jhtml?tpl_redirect_url=https%3A%2F%2Fwww.tmall.com&style=miniall&enup=true&newMini2=true&full_redirect=true&sub=true&from=tmall&allp=assets_css%3D3.0.10/login_pc.css&pms=1650640249767"); - Thread.sleep(10 * 1000L); - - // 预登录 - webDriver.findElement(By.xpath("//input[@name='fm-login-id']")).sendKeys("18600202639"); - webDriver.findElement(By.xpath("//input[@name='fm-login-password']")).sendKeys("19881126yu"); - webDriver.findElement(By.xpath("//*[@class=\"fm-button fm-submit password-login\"]")).click(); - - String oldHandler = webDriver.getWindowHandle(); - webDriver.findElement(By.className("SearchInput--searchInputContent--1USWNEl")).sendKeys("苹果13"); - Thread.sleep(10 * 1000L); - webDriver.findElement(By.className("SearchInput--searchButton--1Sz2UIn")).click(); - Thread.sleep(30 * 1000L); - // 获取当前handler - - Set sets = webDriver.getWindowHandles(); - String newWindow = sets.stream().filter(handler -> !oldHandler.equals(handler)).findFirst().get(); - webDriver.switchTo().window(newWindow); - - List tmElementList = webDriver.findElements(By.className("product-iWrap")); - List productInfos = tmElementList.stream().map(pElement -> { - ProductInfo productInfo = new ProductInfo(); - productInfo.setDescription(pElement.findElement(By.className("productPrice")).getText()); - productInfo.setPrice(pElement.findElement(By.className("productTitle")).getText()); - return productInfo; - }).collect(Collectors.toList()); - - System.out.println(productInfos); - } -} diff --git a/casic-web/pom.xml b/casic-web/pom.xml index 35f0017..eb21475 100644 --- a/casic-web/pom.xml +++ b/casic-web/pom.xml @@ -78,11 +78,6 @@ casic-admin-support ${admin.version} - - com.casic - casic-job-starter - ${extension.version} - diff --git a/casic-web/src/main/java/com/casic/missiles/ZkTest.java b/casic-web/src/main/java/com/casic/missiles/ZkTest.java deleted file mode 100644 index 7e5df40..0000000 --- a/casic-web/src/main/java/com/casic/missiles/ZkTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.casic.missiles; - -import com.casic.missiles.core.util.ZkUtil; -import org.apache.zookeeper.ZooDefs; - -public class ZkTest { - /** - * 白名单 IP添加(待增项) - * - * @param args - * @throws Exception - */ - public static void main(String[] args) throws Exception { - String zkPath = "/ss-job"; - String connectString = "localhost:2181"; - int perms = ZooDefs.Perms.ALL; - String scheme = "digest"; - String auth = "admin:Casic203"; - ZkUtil.addDigests(scheme,perms, null, connectString, zkPath); -// ZkUtil.deletePath(scheme, connectString, zkPath, auth, null); - } -} diff --git a/casic-web/src/main/resources/config/application-dev.yml b/casic-web/src/main/resources/config/application-dev.yml index d3b5903..dc2c417 100644 --- a/casic-web/src/main/resources/config/application-dev.yml +++ b/casic-web/src/main/resources/config/application-dev.yml @@ -4,7 +4,7 @@ spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://111.198.10.15:11336/casic_template2.0?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true + url: jdbc:mysql://111.198.10.15:11336/casic_reptile?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true username: root password: Casic203 jms: @@ -30,8 +30,11 @@ db: init: enable: false + tm: + account: 18600202639 + pwd: 19881126yu webdriver: - driver + path: D:\dev-soft\seleuim-chmod\chromedriver.exe logging: level.root: info level.com.casic: debug diff --git a/casic-web/src/main/resources/config/application-nacos.yml b/casic-web/src/main/resources/config/application-nacos.yml deleted file mode 100644 index 674a98f..0000000 --- a/casic-web/src/main/resources/config/application-nacos.yml +++ /dev/null @@ -1,13 +0,0 @@ -nacos: - # endpoint http://localhost:8080/actuator/nacos-config - # health http://localhost:8080/actuator/health - config: - server-addr: 127.0.0.1:8848 -management: -# endpoints: -# web: -# exposure: -# include: * - endpoint: - health: - show-details: always \ No newline at end of file diff --git a/casic-web/src/main/resources/config/application.yml b/casic-web/src/main/resources/config/application.yml index 1d177f6..ba41f8b 100644 --- a/casic-web/src/main/resources/config/application.yml +++ b/casic-web/src/main/resources/config/application.yml @@ -8,11 +8,6 @@ multipart: max-file-size: 50MB max-request-size: 80MB - kafka: - #139.198.17.169:9092 - bootstrap-servers: localhost:9092 - consumer: # 指定默认消费者group id - group-id: 21e87b6b-175d-4600-a1f0-690c360ce532 jms: pub-sub-domain: true mybatis-plus: