Browse Source

seo 重构

zq940222 5 tháng trước cách đây
mục cha
commit
1d4c49c0ec
23 tập tin đã thay đổi với 702 bổ sung397 xóa
  1. 4 0
      jeecg-module-system/jeecg-system-api/jeecg-system-local-api/src/main/java/org/jeecg/common/system/api/ISysBaseAPI.java
  2. 11 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/common/util/DateUtil.java
  3. 0 31
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/config/RocketMQConfig.java
  4. 4 5
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/enquiry/controller/AdwebEnquiryController.java
  5. 209 28
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/controller/SeoKeywordsController.java
  6. 0 162
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/controller/SeoMarketPlanController.java
  7. 28 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/dto/AvesApiSearchKeywordsDTO.java
  8. 36 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/entity/SeoKeywords.java
  9. 4 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/entity/SeoKeywordsSerp.java
  10. 0 72
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/entity/SeoMarketPlan.java
  11. 29 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/mapper/SeoKeywordsMapper.java
  12. 0 21
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/mapper/SeoMarketPlanMapper.java
  13. 9 4
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/mapper/SeoPlanSubscriptionMapper.java
  14. 86 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/mapper/xml/SeoKeywordsMapper.xml
  15. 0 18
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/mapper/xml/SeoMarketPlanMapper.xml
  16. 14 1
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/mapper/xml/SeoPlanSubscriptionMapper.xml
  17. 6 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/service/ISearchKeywordsService.java
  18. 16 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/service/ISeoKeywordsService.java
  19. 0 14
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/service/ISeoMarketPlanService.java
  20. 134 22
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/service/impl/SearchKeywordsServiceImpl.java
  21. 49 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/service/impl/SeoKeywordsServiceImpl.java
  22. 0 19
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/service/impl/SeoMarketPlanServiceImpl.java
  23. 63 0
      jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysBaseApiImpl.java

+ 4 - 0
jeecg-module-system/jeecg-system-api/jeecg-system-local-api/src/main/java/org/jeecg/common/system/api/ISysBaseAPI.java

@@ -549,4 +549,8 @@ public interface ISysBaseAPI extends CommonAPI {
     boolean isAdmin();
 
     List<String> getOemGroupUids();
+
+    boolean isNotOwnSite(Integer siteId);
+
+    boolean isNotOwnSite(String siteCode);
 }

+ 11 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/common/util/DateUtil.java

@@ -14,6 +14,17 @@ import java.util.*;
  */
 public class DateUtil {
 
+    /**
+     * 时间格式(yyyy-MM-dd)
+     */
+    public final static String DATE_PATTERN = "yyyy-MM-dd";
+    /**
+     * 时间格式(yyyy-MM-dd HH:mm:ss)
+     */
+    public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
+
+    public final static String SUBJECT_DATE = "yyyy/MM/dd";
+
     public static final ZoneId DEFAULT_ZONE_ID = ZoneId.of("Asia/Shanghai");
 
     /**

+ 0 - 31
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/config/RocketMQConfig.java

@@ -1,31 +0,0 @@
-package org.jeecg.modules.adweb.config;
-
-import org.apache.rocketmq.client.producer.DefaultMQProducer;
-import org.apache.rocketmq.spring.core.RocketMQTemplate;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-@Configuration
-public class RocketMQConfig {
-
-    @Value("${rocketmq.producer.group}")
-    private String producerGroup;
-
-    @Value("${rocketmq.name-server}")
-    private String nameServer;
-
-    /**
-     * 由于使用的Spring版本是3.0.0以上,与rocketMq不是很兼容,对于rocketMqTemplate
-     * 的自动注入存在差异,如果不采用这种方式注入则会报出缺少bean的信息
-     */
-    @Bean("RocketMQTemplate")
-    public RocketMQTemplate rocketMqTemplate(){
-        RocketMQTemplate rocketMqTemplate = new RocketMQTemplate();
-        DefaultMQProducer defaultMqProducer = new DefaultMQProducer();
-        defaultMqProducer.setProducerGroup(producerGroup);
-        defaultMqProducer.setNamesrvAddr(nameServer);
-        rocketMqTemplate.setProducer(defaultMqProducer);
-        return rocketMqTemplate;
-    }
-}

+ 4 - 5
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/enquiry/controller/AdwebEnquiryController.java

@@ -3,20 +3,22 @@ package org.jeecg.modules.adweb.enquiry.controller;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
+
 import jakarta.annotation.Resource;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
+
 import lombok.extern.slf4j.Slf4j;
+
 import org.apache.commons.lang.StringUtils;
-import org.apache.rocketmq.spring.core.RocketMQTemplate;
 import org.apache.shiro.SecurityUtils;
 import org.jeecg.common.api.vo.Result;
 import org.jeecg.common.aspect.annotation.AutoLog;
 import org.jeecg.common.system.base.controller.JeecgController;
 import org.jeecg.common.system.vo.DictModel;
-import org.jeecg.common.system.vo.DictPropertyModel;
 import org.jeecg.common.system.vo.LoginUser;
 import org.jeecg.common.util.FastJsonUtil;
 import org.jeecg.modules.adweb.common.constant.CompConstants;
@@ -64,9 +66,6 @@ public class AdwebEnquiryController extends JeecgController<AdwebEnquiry, IAdweb
     private Boolean demoFlag;
 
     @Resource
-    private RocketMQTemplate rocketMQTemplate;
-
-    @Resource
     private AdwebEnquiryMapper adwebEnquiryMapper;
 
     @Autowired

+ 209 - 28
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/controller/SeoKeywordsController.java

@@ -1,43 +1,45 @@
 package org.jeecg.modules.adweb.serp.controller;
 
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import org.jeecg.common.api.vo.Result;
-import org.jeecg.common.system.query.QueryGenerator;
-import org.jeecg.common.util.oConvertUtils;
-import org.jeecg.modules.adweb.serp.entity.SeoKeywords;
-import org.jeecg.modules.adweb.serp.service.ISeoKeywordsService;
-
+import cn.hutool.core.io.IoUtil;
+import cn.hutool.poi.excel.ExcelUtil;
+import cn.hutool.poi.excel.ExcelWriter;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.xkcoding.http.util.StringUtil;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+
+import jakarta.servlet.ServletOutputStream;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+
 import lombok.extern.slf4j.Slf4j;
 
-import org.jeecgframework.poi.excel.ExcelImportUtil;
-import org.jeecgframework.poi.excel.def.NormalExcelConstants;
-import org.jeecgframework.poi.excel.entity.ExportParams;
-import org.jeecgframework.poi.excel.entity.ImportParams;
-import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.common.aspect.annotation.AutoLog;
+import org.jeecg.common.system.api.ISysBaseAPI;
 import org.jeecg.common.system.base.controller.JeecgController;
+import org.jeecg.common.system.query.QueryGenerator;
+import org.jeecg.modules.adweb.common.util.ListUtil;
+import org.jeecg.modules.adweb.serp.dto.AvesApiSearchKeywordsDTO;
+import org.jeecg.modules.adweb.serp.entity.SeoKeywords;
+import org.jeecg.modules.adweb.serp.entity.SeoKpiStatistics;
+import org.jeecg.modules.adweb.serp.service.ISearchKeywordsService;
+import org.jeecg.modules.adweb.serp.service.ISeoKeywordsService;
+import org.jeecg.modules.adweb.serp.service.ISeoKpiStatisticsService;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
-import org.springframework.web.multipart.MultipartFile;
-import org.springframework.web.multipart.MultipartHttpServletRequest;
 import org.springframework.web.servlet.ModelAndView;
-import com.alibaba.fastjson.JSON;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import org.jeecg.common.aspect.annotation.AutoLog;
-import org.springframework.security.access.prepost.PreAuthorize;
 
- /**
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+
+/**
  * @Description: 关键词
  * @Author: jeecg-boot
  * @Date:   2024-10-15
@@ -50,6 +52,15 @@ import org.springframework.security.access.prepost.PreAuthorize;
 public class SeoKeywordsController extends JeecgController<SeoKeywords, ISeoKeywordsService> {
 	@Autowired
 	private ISeoKeywordsService seoKeywordsService;
+
+	@Autowired
+	ISeoKpiStatisticsService seoKpiStatisticsService;
+
+	@Autowired
+	ISearchKeywordsService searchKeywordsService;
+
+	@Autowired
+	private ISysBaseAPI sysBaseAPI;
 	
 	/**
 	 * 分页列表查询
@@ -175,4 +186,174 @@ public class SeoKeywordsController extends JeecgController<SeoKeywords, ISeoKeyw
         return super.importExcel(request, response, SeoKeywords.class);
     }
 
+	 /**
+	  * 关键词排名页面 - 列表数据
+	  */
+	 @AutoLog(value = "营销推广-SEO-关键词排名统计查询接口")
+	 @RequestMapping(value = "/keywordList")
+	 public Result<?> queryRankInfoList(AvesApiSearchKeywordsDTO avesApiSearchKeywordsDTO,
+										@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
+										@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
+										HttpServletRequest req) throws Exception {
+		 if (sysBaseAPI.isNotOwnSite(avesApiSearchKeywordsDTO.getUserFlag())) {
+			 return Result.OK(new Page<>());
+		 }
+		 // 参数判断
+		 IPage<SeoKeywords> pageList = new Page<>();
+		 String userFlag = req.getParameter("userFlag");
+		 if (StringUtil.isEmpty(userFlag)) {
+			 userFlag = avesApiSearchKeywordsDTO.getUserFlag();
+		 }
+		 if (StringUtil.isEmpty(userFlag)) {
+			 log.info("缺少用户flag参数");
+			 return Result.OK(pageList);
+		 }
+
+		 String historyId = avesApiSearchKeywordsDTO.getHistoryId();
+
+		 // 查询是否具有关键词优化指标
+		 boolean haveAppointKeyword = false;
+		 boolean haveLongTail = false;
+		 QueryWrapper<SeoKpiStatistics> statisticsQueryWrapper = new QueryWrapper<>();
+		 statisticsQueryWrapper.eq("host_code", userFlag);
+		 statisticsQueryWrapper.eq("del_flag", 0);
+		 statisticsQueryWrapper.eq("type", 1);
+		 statisticsQueryWrapper.eq("history_id", historyId);
+		 List<SeoKpiStatistics> seoKpiStatisticsList = seoKpiStatisticsService.list(statisticsQueryWrapper);
+		 if (ListUtil.isEmpty(seoKpiStatisticsList)) {
+			 return Result.OK(pageList);
+		 }
+		 for (SeoKpiStatistics kpiStatistics : seoKpiStatisticsList) {
+			 if (kpiStatistics.getKpiTarget() == null || kpiStatistics.getKpiTarget() == 0) {
+				 continue;
+			 }
+			 if ("APPOINT_KEYWORDS".equals(kpiStatistics.getKpiCode())) {
+				 haveAppointKeyword = true;
+			 } else if ("LONG_TAIL_KEYWORDS".equals(kpiStatistics.getKpiCode())) {
+				 haveLongTail = true;
+			 }
+		 }
+
+		 if (!haveAppointKeyword && !haveLongTail) {
+			 return Result.OK(pageList);
+		 }
+
+		 Integer keywordType = avesApiSearchKeywordsDTO.getKeywordType();
+		 if (haveAppointKeyword && !haveLongTail) {
+			 keywordType = 1;
+		 } else if (!haveAppointKeyword && haveLongTail) {
+			 keywordType = 2;
+		 }
+
+		 // 查询关键词
+		 String column = req.getParameter("column");
+		 String order = req.getParameter("order");
+		 String buttonColumn = req.getParameter("buttonColmn");
+		 String buttonSort = req.getParameter("buttonSort");
+		 Page<SeoKeywords> page = new Page<SeoKeywords>(pageNo, pageSize);
+		 List<String> dateList = seoKeywordsService.getKeywordsLastSevenDays(userFlag,keywordType,historyId);
+		 pageList = seoKeywordsService.getKeywordList(page,
+				 avesApiSearchKeywordsDTO.getRankStart(),
+				 avesApiSearchKeywordsDTO.getRankEnd(),
+				 avesApiSearchKeywordsDTO.getKeywords(),
+				 userFlag,
+				 keywordType,
+				 avesApiSearchKeywordsDTO.getReachStandard() != null && avesApiSearchKeywordsDTO.getReachStandard() == 1,
+				 historyId,
+				 column,
+				 order,
+				 buttonColumn,
+				 buttonSort,
+				 dateList);
+
+		 // 给关键词对象增加排名信息
+		 if(pageList == null){
+			 return Result.error("未获取到关键词数据");
+		 }
+		 searchKeywordsService.addRankInfoByIntervalTimeByType(pageList.getRecords(), avesApiSearchKeywordsDTO.getKeywordType(),userFlag,historyId,dateList);
+		 log.info(pageList.toString());
+		 return Result.OK(pageList);
+	 }
+
+	/**
+	 * Excel导出
+	 * 关键词排名的导出
+	 * @param avesApiSearchKeywordsDTO 查询参数
+	 * @return 询盘列表
+	 */
+	@RequestMapping(value = "/exportExcel")
+	public void exportExcel(AvesApiSearchKeywordsDTO avesApiSearchKeywordsDTO,
+							HttpServletRequest req,
+							HttpServletResponse response) throws Exception {
+		Result res = this.queryRankInfoList(avesApiSearchKeywordsDTO, 1, 5000, req);
+		if (res == null || res.getResult() == null) {
+			return;
+		}
+		IPage<SeoKeywords> pageList = (IPage<SeoKeywords>) res.getResult();
+		if (pageList.getRecords().size() == 0) {
+			return;
+		}
+		ArrayList<String> columns = null;
+		// 表头信息
+		if (sysBaseAPI.isAdmin()) {
+			columns = new ArrayList<>(Arrays.asList("序号", "关键词", "url", "关键词类型"));
+		} else {
+			columns = new ArrayList<>(Arrays.asList("序号", "关键词", "关键词类型"));
+		}
+
+		// 将关键词信息改为可以导出的格式
+		List<Map<String, Object>> list = new ArrayList<>();
+		List<SeoKeywords> enquiryList = pageList.getRecords();
+
+		List<String> dates = pageList.getRecords().get(0).getDateList();
+		columns.addAll(dates);
+
+		boolean isAdmin = sysBaseAPI.isAdmin();
+
+		for (int i = 0; i < enquiryList.size(); i++) {
+			SeoKeywords seoKeywords = enquiryList.get(i);
+			Map<String, Object> map = new LinkedHashMap<>();
+			map.put("序号", i + 1);
+			map.put("关键词", seoKeywords.getKeywords());
+			if (isAdmin) {
+				map.put("url", seoKeywords.getPositionUrl());
+			}
+			if(seoKeywords.getKeywordType() == 1) {
+				map.put("关键词类型", "指定词");
+			} else if(seoKeywords.getKeywordType() == 2) {
+				map.put("关键词类型", "长尾词");
+			}
+			// 遍历日期
+			for (String date : dates) {
+				map.put(date,Integer.valueOf(seoKeywords.getRankInfo().get(date) == null ? "0" : seoKeywords.getRankInfo().get(date)));
+			}
+			list.add(map);
+		}
+		StringBuilder fileName = new StringBuilder();
+		fileName.append("关键词排名导出");
+
+		response.setContentType("application/vnd.ms-excel;charset=utf-8");
+		// test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码
+		ServletOutputStream out = null;
+		ExcelWriter writer = ExcelUtil.getWriter(true);
+		try {
+			Sheet sheet = writer.getSheet();
+			sheet.setDefaultColumnWidth(12);
+			sheet.setDefaultRowHeightInPoints(20);
+			// 设置请求头属性
+			response.setHeader("Content-Disposition", "attachment;filename=" + new String((fileName + ".xlsx").getBytes(), StandardCharsets.ISO_8859_1));
+			out = response.getOutputStream();
+			writer.write(list, true);
+			searchKeywordsService.setSizeColumn(sheet, list.get(0).size());
+			// 写出到文件
+			writer.flush(out, true);
+			// 关闭writer,释放内存
+			writer.close();
+			// 此处记得关闭输出Servlet流
+			IoUtil.close(out);
+		} catch (IOException e) {
+			log.error(e.getMessage());
+			e.printStackTrace();
+		}
+	}
 }

+ 0 - 162
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/controller/SeoMarketPlanController.java

@@ -1,162 +0,0 @@
-package org.jeecg.modules.adweb.serp.controller;
-
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.extern.slf4j.Slf4j;
-import org.jeecg.common.api.vo.Result;
-import org.jeecg.common.aspect.annotation.AutoLog;
-import org.jeecg.common.system.base.controller.JeecgController;
-import org.jeecg.common.system.query.QueryGenerator;
-import org.jeecg.modules.adweb.serp.entity.SeoMarketPlan;
-import org.jeecg.modules.adweb.serp.service.ISeoMarketPlanService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.web.servlet.ModelAndView;
-
-import java.util.Arrays;
-
- /**
- * @Description: 营销方案
- * @Author: jeecg-boot
- * @Date:   2024-10-15
- * @Version: V1.0
- */
-@Tag(name="营销方案")
-@RestController
-@RequestMapping("/serp/seoMarketPlan")
-@Slf4j
-public class SeoMarketPlanController extends JeecgController<SeoMarketPlan, ISeoMarketPlanService> {
-	@Autowired
-	private ISeoMarketPlanService seoMarketPlanService;
-	
-	/**
-	 * 分页列表查询
-	 *
-	 * @param seoMarketPlan
-	 * @param pageNo
-	 * @param pageSize
-	 * @param req
-	 * @return
-	 */
-	//@AutoLog(value = "营销方案-分页列表查询")
-	@Operation(summary="营销方案-分页列表查询")
-	@GetMapping(value = "/list")
-	public Result<IPage<SeoMarketPlan>> queryPageList(SeoMarketPlan seoMarketPlan,
-								   @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
-								   @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
-								   HttpServletRequest req) {
-		QueryWrapper<SeoMarketPlan> queryWrapper = QueryGenerator.initQueryWrapper(seoMarketPlan, req.getParameterMap());
-		Page<SeoMarketPlan> page = new Page<SeoMarketPlan>(pageNo, pageSize);
-		IPage<SeoMarketPlan> pageList = seoMarketPlanService.page(page, queryWrapper);
-		return Result.OK(pageList);
-	}
-	
-	/**
-	 *   添加
-	 *
-	 * @param seoMarketPlan
-	 * @return
-	 */
-	@AutoLog(value = "营销方案-添加")
-	@Operation(summary="营销方案-添加")
-	@PreAuthorize("@jps.requiresPermissions('serp:seo_market_plan:add')")
-	@PostMapping(value = "/add")
-	public Result<String> add(@RequestBody SeoMarketPlan seoMarketPlan) {
-		seoMarketPlanService.save(seoMarketPlan);
-		return Result.OK("添加成功!");
-	}
-	
-	/**
-	 *  编辑
-	 *
-	 * @param seoMarketPlan
-	 * @return
-	 */
-	@AutoLog(value = "营销方案-编辑")
-	@Operation(summary="营销方案-编辑")
-    @PreAuthorize("@jps.requiresPermissions('serp:seo_market_plan:edit')")
-	@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
-	public Result<String> edit(@RequestBody SeoMarketPlan seoMarketPlan) {
-		seoMarketPlanService.updateById(seoMarketPlan);
-		return Result.OK("编辑成功!");
-	}
-	
-	/**
-	 *   通过id删除
-	 *
-	 * @param id
-	 * @return
-	 */
-	@AutoLog(value = "营销方案-通过id删除")
-	@Operation(summary="营销方案-通过id删除")
-    @PreAuthorize("@jps.requiresPermissions('serp:seo_market_plan:delete')")
-	@DeleteMapping(value = "/delete")
-	public Result<String> delete(@RequestParam(name="id",required=true) String id) {
-		seoMarketPlanService.removeById(id);
-		return Result.OK("删除成功!");
-	}
-	
-	/**
-	 *  批量删除
-	 *
-	 * @param ids
-	 * @return
-	 */
-	@AutoLog(value = "营销方案-批量删除")
-	@Operation(summary="营销方案-批量删除")
-    @PreAuthorize("@jps.requiresPermissions('serp:seo_market_plan:deleteBatch')")
-	@DeleteMapping(value = "/deleteBatch")
-	public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
-		this.seoMarketPlanService.removeByIds(Arrays.asList(ids.split(",")));
-		return Result.OK("批量删除成功!");
-	}
-	
-	/**
-	 * 通过id查询
-	 *
-	 * @param id
-	 * @return
-	 */
-	//@AutoLog(value = "营销方案-通过id查询")
-	@Operation(summary="营销方案-通过id查询")
-	@GetMapping(value = "/queryById")
-	public Result<SeoMarketPlan> queryById(@RequestParam(name="id",required=true) String id) {
-		SeoMarketPlan seoMarketPlan = seoMarketPlanService.getById(id);
-		if(seoMarketPlan==null) {
-			return Result.error("未找到对应数据");
-		}
-		return Result.OK(seoMarketPlan);
-	}
-
-    /**
-    * 导出excel
-    *
-    * @param request
-    * @param seoMarketPlan
-    */
-    @PreAuthorize("@jps.requiresPermissions('serp:seo_market_plan:exportXls')")
-    @RequestMapping(value = "/exportXls")
-    public ModelAndView exportXls(HttpServletRequest request, SeoMarketPlan seoMarketPlan) {
-        return super.exportXls(request, seoMarketPlan, SeoMarketPlan.class, "营销方案");
-    }
-
-    /**
-      * 通过excel导入数据
-    *
-    * @param request
-    * @param response
-    * @return
-    */
-    @PreAuthorize("@jps.requiresPermissions('serp:seo_market_plan:importExcel')")
-    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
-    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
-        return super.importExcel(request, response, SeoMarketPlan.class);
-    }
-
-}

+ 28 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/dto/AvesApiSearchKeywordsDTO.java

@@ -0,0 +1,28 @@
+package org.jeecg.modules.adweb.serp.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+
+/**
+ * @author Zenas
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class AvesApiSearchKeywordsDTO {
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private Date startTime;
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private Date endTime;
+    private Integer keywordType;
+    private String keywords;
+    private Integer rankStart;
+    private Integer rankEnd;
+    private Integer reachStandard;
+    private String userFlag;
+    private String historyId;
+}

+ 36 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/entity/SeoKeywords.java

@@ -1,6 +1,7 @@
 package org.jeecg.modules.adweb.serp.entity;
 
 import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
@@ -13,6 +14,8 @@ import org.springframework.format.annotation.DateTimeFormat;
 
 import java.io.Serializable;
 import java.util.Date;
+import java.util.List;
+import java.util.Map;
 
 /**
  * @Description: 关键词
@@ -123,4 +126,37 @@ public class SeoKeywords implements Serializable {
 	@Excel(name = "对应套餐绑定表ID", width = 15)
     @Schema(description = "对应套餐绑定表ID")
     private String historyId;
+    @TableField(exist = false)
+    private String ipAddress;
+    @TableField(exist = false)
+    private String latestRank;
+    @TableField(exist = false)
+    private String searchUrl;
+    @TableField(exist = false)
+    private Map<String, String> rankInfo;
+    @TableField(exist = false)
+    private Integer siteId;
+    @TableField(exist = false)
+    private String value;
+    @TableField(exist = false)
+    private String order;
+    @TableField(exist = false)
+    private String column;
+    /**
+     * 关键词排名
+     */
+    @TableField(exist = false)
+    private Integer keywordRank;
+
+    /**
+     * 关键词字符长度
+     */
+    @TableField(exist = false)
+    private Integer keywordsLength;
+
+    /**
+     * 关键词时间范围
+     */
+    @TableField(exist = false)
+    private List<String> dateList;
 }

+ 4 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/entity/SeoKeywordsSerp.java

@@ -1,5 +1,6 @@
 package org.jeecg.modules.adweb.serp.entity;
 
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
 
@@ -75,4 +76,7 @@ public class SeoKeywordsSerp implements Serializable {
     @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
     @Schema(description = "搜索时间")
     private Date seDatetime;
+
+    @TableField(exist = false)
+    private String key;
 }

+ 0 - 72
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/entity/SeoMarketPlan.java

@@ -1,72 +0,0 @@
-package org.jeecg.modules.adweb.serp.entity;
-
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.experimental.Accessors;
-import org.jeecgframework.poi.excel.annotation.Excel;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.io.Serializable;
-import java.util.Date;
-
-/**
- * @Description: 营销方案
- * @Author: jeecg-boot
- * @Date:   2024-10-15
- * @Version: V1.0
- */
-@Data
-@TableName("seo_market_plan")
-@Accessors(chain = true)
-@EqualsAndHashCode(callSuper = false)
-@Schema(description="营销方案")
-public class SeoMarketPlan implements Serializable {
-    private static final long serialVersionUID = 1L;
-
-	/**主键*/
-	@TableId(type = IdType.ASSIGN_ID)
-    @Schema(description = "主键")
-    private String id;
-	/**营销方案编码*/
-	@Excel(name = "营销方案编码", width = 15)
-    @Schema(description = "营销方案编码")
-    private String planCode;
-	/**方案名称*/
-	@Excel(name = "方案名称", width = 15)
-    @Schema(description = "方案名称")
-    private String planName;
-	/**营销方案类型:SEO、ARTICLE_BUILDER*/
-	@Excel(name = "营销方案类型:SEO、ARTICLE_BUILDER", width = 15)
-    @Schema(description = "营销方案类型:SEO、ARTICLE_BUILDER")
-    private String marketType;
-	/**关键词数量*/
-	@Excel(name = "关键词数量", width = 15)
-    @Schema(description = "关键词数量")
-    private Integer keywordCount;
-	/**关键词达标目标Top?*/
-	@Excel(name = "关键词达标目标Top?", width = 15)
-    @Schema(description = "关键词达标目标Top?")
-    private Integer target;
-	/**服务时间*/
-	@Excel(name = "服务时间", width = 15)
-    @Schema(description = "服务时间")
-    private Integer serviceTime;
-	/**状态*/
-	@Excel(name = "状态", width = 15)
-    @Schema(description = "状态")
-    private Integer status;
-	/**价格*/
-	@Excel(name = "价格", width = 15)
-    @Schema(description = "价格")
-    private Double price;
-	/**创建时间*/
-	@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
-    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
-    @Schema(description = "创建时间")
-    private Date createTime;
-}

+ 29 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/mapper/SeoKeywordsMapper.java

@@ -1,6 +1,8 @@
 package org.jeecg.modules.adweb.serp.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+
 import org.apache.ibatis.annotations.Param;
 import org.jeecg.modules.adweb.serp.entity.SeoKeywords;
 import org.jeecg.modules.adweb.serp.vo.RankInfoVO;
@@ -30,4 +32,31 @@ public interface SeoKeywordsMapper extends BaseMapper<SeoKeywords> {
      */
     RankInfoVO queryKeywordNumByRankRange(@Param("userFlag") String userFlag, @Param("historyId") String historyId, @Param("rankStart") Integer rankStart, @Param("rankEnd") Integer rankEnd, @Param("dateStr") String dateStr, @Param("keywordType") String keywordType);
 
+    /**
+     * 根据站点code获取关键词达标标准
+     *
+     * @param siteCode 站点code
+     * @return 达标标准
+     */
+    int getKeywordStandard(String siteCode);
+
+    /**
+     * 获取关键词列表
+     *
+     * @return 关键词列表
+     */
+    IPage<SeoKeywords> getKeywordList(IPage<SeoKeywords> page,
+                                      Integer rankStart,
+                                      Integer rankEnd,
+                                      boolean isCustomer,
+                                      String keyword,
+                                      String siteCode,
+                                      Integer keywordType,
+                                      String datesStr,
+                                      String historyId,
+                                      String column,
+                                      String order,
+                                      String buttonColumn,
+                                      String buttonSort);
+
 }

+ 0 - 21
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/mapper/SeoMarketPlanMapper.java

@@ -1,21 +0,0 @@
-package org.jeecg.modules.adweb.serp.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import org.jeecg.modules.adweb.serp.entity.SeoMarketPlan;
-
-/**
- * @Description: 营销方案
- * @Author: jeecg-boot
- * @Date:   2024-10-15
- * @Version: V1.0
- */
-public interface SeoMarketPlanMapper extends BaseMapper<SeoMarketPlan> {
-
-    /**
-     * 根据站点code获取关键词达标标准
-     *
-     * @param siteCode 站点code
-     * @return 达标标准
-     */
-    int getKeywordStandard(String siteCode);
-}

+ 9 - 4
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/mapper/SeoPlanSubscriptionMapper.java

@@ -1,11 +1,10 @@
 package org.jeecg.modules.adweb.serp.mapper;
 
-import java.util.List;
 
-import org.apache.ibatis.annotations.Param;
-import org.jeecg.modules.adweb.serp.entity.SeoPlanSubscription;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 
+import org.jeecg.modules.adweb.serp.entity.SeoPlanSubscription;
+
 /**
  * @Description: seo套餐订购
  * @Author: jeecg-boot
@@ -13,5 +12,11 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  * @Version: V1.0
  */
 public interface SeoPlanSubscriptionMapper extends BaseMapper<SeoPlanSubscription> {
-
+    /**
+     * 根据站点code获取关键词达标标准
+     *
+     * @param siteCode 站点code
+     * @return 达标标准
+     */
+    int getKeywordStandard(String siteCode);
 }

+ 86 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/mapper/xml/SeoKeywordsMapper.xml

@@ -74,4 +74,90 @@
         GROUP BY
         t.type
     </select>
+    <select id="getKeywordStandard" resultType="java.lang.Integer">
+        SELECT
+            IF(COUNT(*) = 0 OR t1.target IS NULL, 10, t1.target)
+        FROM
+            seo_market_plan t1,
+            seo_plan_subscription t2,
+            adweb_site t3
+        WHERE
+            t2.`status` = 1
+          AND t1.id = t2.plan_id
+          AND t2.site_id = t3.id
+          AND t3.`code` = #{siteCode}
+    </select>
+    <select id="getKeywordList" resultType="org.jeecg.modules.adweb.serp.entity.SeoKeywords">
+        SELECT
+        DISTINCT t1.*,CHAR_LENGTH( keywords ) keywordsLength
+        FROM
+        seo_keywords t1
+        <where>
+
+            <if test="keyword != null and keyword != ''">
+                AND t1.keywords LIKE CONCAT('%', #{keyword}, '%')
+            </if>
+            <if test="siteCode != null and siteCode != ''">
+                AND t1.user_flag = #{siteCode}
+            </if>
+            <if test="keywordType != null">
+                AND t1.keyword_type = #{keywordType}
+            </if>
+            <if test="rankStart != null">
+                AND t1.last_rank >= #{rankStart}
+            </if>
+            <if test="rankEnd != null">
+                AND #{rankEnd} >= t1.last_rank
+            </if>
+            AND t1.app_key = 'adweb'
+            AND t1.`status` =  1
+            <if test="!historyId">
+                AND t1.history_id = #{historyId}
+            </if>
+            AND
+            (
+            id IN
+            (
+            SELECT
+            t3.keywords_id
+            FROM
+            (
+            SELECT
+            keywords_id,MAX(t1.rank_absolute) max_rank
+            FROM
+            seo_keywords_serp t1,
+            seo_keywords t2
+            WHERE
+            t2.`status` = 1
+            AND t1.keywords_id = t2.id
+            AND t2.app_key = 'adweb'
+            <if test="siteCode != null and siteCode != ''">
+                AND t2.user_flag = #{siteCode}
+            </if>
+            <if test="keywordType != null">
+                AND t2.keyword_type = #{keywordType}
+            </if>
+            <if test="!historyId">
+                AND t2.history_id = #{historyId}
+            </if>
+            AND se_date IN ${datesStr}
+            GROUP BY keywords_id
+            ) t3
+            WHERE t3.max_rank <![CDATA[ <>]]> 0
+            )
+            <if test="!isCustomer">
+                OR t1.`status` = 1
+            </if>
+            )
+        </where>
+        ORDER BY
+        last_rank + IF(t1.status = 0, 10000, 0) + IF(t1.last_rank = 0, 1000, 0)+ IF(t1.keyword_type = 2, 100, 0)
+        <if test="buttonColumn != null and buttonColumn == 'ranking'">
+            ${buttonSort}
+        </if>
+        <if test="buttonColumn != null and buttonColumn == 'words'">
+            ,CHAR_LENGTH(keywords) ${buttonSort}
+        </if>
+        ,create_time
+    </select>
 </mapper>

+ 0 - 18
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/mapper/xml/SeoMarketPlanMapper.xml

@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="org.jeecg.modules.adweb.serp.mapper.SeoMarketPlanMapper">
-    <select id="getKeywordStandard" resultType="java.lang.Integer">
-        SELECT
-            IF(COUNT(*) = 0 OR t1.target IS NULL, 10, t1.target)
-        FROM
-            seo_market_plan t1,
-            seo_plan_subscription t2,
-            adweb_site t3
-        WHERE
-            t2.`status` = 1
-          AND t1.id = t2.plan_id
-          AND t2.site_id = t3.id
-          AND t3.`code` = #{siteCode}
-        GROUP BY t1.target
-    </select>
-</mapper>

+ 14 - 1
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/mapper/xml/SeoPlanSubscriptionMapper.xml

@@ -1,5 +1,18 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="org.jeecg.modules.adweb.serp.mapper.SeoPlanSubscriptionMapper">
-
+    <select id="getKeywordStandard" resultType="java.lang.Integer">
+        SELECT
+            IF(COUNT(*) = 0 OR t1.target IS NULL, 10, t1.target)
+        FROM
+            subscribe_plan t1,
+            seo_plan_subscription t2,
+            adweb_site t3
+        WHERE
+            t2.`status` = 1
+          AND t1.id = t2.plan_id
+          AND t2.site_id = t3.id
+          AND t3.`code` = #{siteCode}
+        GROUP BY t1.target
+    </select>
 </mapper>

+ 6 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/service/ISearchKeywordsService.java

@@ -1,6 +1,8 @@
 package org.jeecg.modules.adweb.serp.service;
 
+import org.apache.poi.ss.usermodel.Sheet;
 import org.jeecg.modules.adweb.serp.entity.ComprehensiveStatistics;
+import org.jeecg.modules.adweb.serp.entity.SeoKeywords;
 import org.jeecg.modules.adweb.serp.vo.SeoRankInfoVO;
 
 import java.text.ParseException;
@@ -17,4 +19,8 @@ public interface ISearchKeywordsService {
     Map getRankInfo(String siteCode, String historyId) throws ParseException;
 
     List<SeoRankInfoVO> getSeoRankInfo(String siteCode, String historyId) throws ParseException;
+
+    void addRankInfoByIntervalTimeByType(List<SeoKeywords> keywordList, Integer keywordType, String siteCode, String historyId, List<String> dateList) throws Exception;
+
+    void setSizeColumn(Sheet sheet, int size);
 }

+ 16 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/service/ISeoKeywordsService.java

@@ -1,10 +1,12 @@
 package org.jeecg.modules.adweb.serp.service;
 
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
 
 import org.jeecg.modules.adweb.serp.entity.SeoKeywords;
 import org.jeecg.modules.adweb.serp.vo.RankInfoVO;
 
+import java.text.ParseException;
 import java.util.List;
 
 /**
@@ -18,4 +20,18 @@ public interface ISeoKeywordsService extends IService<SeoKeywords> {
     List<String> getKeywordsLastSevenDays(String userFlag, Integer keywordType, String historyId);
 
     RankInfoVO getSeoRankInfo(String siteCode, String historyId, Integer rankStart, Integer rankEnd, String dateStr, String keywordType);
+
+    IPage<SeoKeywords> getKeywordList(IPage<SeoKeywords> page,
+                                      Integer rankStart,
+                                      Integer rankEnd,
+                                      String keyword,
+                                      String siteCode,
+                                      Integer keywordType,
+                                      boolean reachStandard,
+                                      String historyId,
+                                      String column,
+                                      String order,
+                                      String buttonColumn,
+                                      String buttonSort,
+                                      List<String> dateList) throws ParseException;
 }

+ 0 - 14
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/service/ISeoMarketPlanService.java

@@ -1,14 +0,0 @@
-package org.jeecg.modules.adweb.serp.service;
-
-import org.jeecg.modules.adweb.serp.entity.SeoMarketPlan;
-import com.baomidou.mybatisplus.extension.service.IService;
-
-/**
- * @Description: 营销方案
- * @Author: jeecg-boot
- * @Date:   2024-10-15
- * @Version: V1.0
- */
-public interface ISeoMarketPlanService extends IService<SeoMarketPlan> {
-
-}

+ 134 - 22
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/service/impl/SearchKeywordsServiceImpl.java

@@ -1,20 +1,23 @@
 package org.jeecg.modules.adweb.serp.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.xkcoding.http.util.StringUtil;
 
 import jakarta.annotation.Resource;
 
 import lombok.extern.slf4j.Slf4j;
 
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellType;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
 import org.jeecg.common.util.FastJsonUtil;
 import org.jeecg.modules.adweb.common.util.DateUtil;
 import org.jeecg.modules.adweb.common.util.ListUtil;
-import org.jeecg.modules.adweb.serp.entity.ComprehensiveStatistics;
-import org.jeecg.modules.adweb.serp.entity.HistoryReachStandardSite;
-import org.jeecg.modules.adweb.serp.entity.SeoKpiStatistics;
-import org.jeecg.modules.adweb.serp.entity.SeoPlanSubscription;
+import org.jeecg.modules.adweb.serp.entity.*;
 import org.jeecg.modules.adweb.serp.mapper.SeoKeywordsMapper;
-import org.jeecg.modules.adweb.serp.mapper.SeoMarketPlanMapper;
+import org.jeecg.modules.adweb.serp.mapper.SeoPlanSubscriptionMapper;
 import org.jeecg.modules.adweb.serp.service.*;
 import org.jeecg.modules.adweb.serp.vo.RankInfoVO;
 import org.jeecg.modules.adweb.serp.vo.SeoRankInfoVO;
@@ -24,8 +27,8 @@ import org.springframework.stereotype.Service;
 
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
-import java.time.LocalDate;
 import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * @author Zenas
@@ -36,12 +39,14 @@ public class SearchKeywordsServiceImpl implements ISearchKeywordsService {
 
     @Autowired private ISeoKpiStatisticsService seoKpiStatisticsService;
 
-    @Resource private SeoMarketPlanMapper seoMarketPlanMapper;
+    @Resource private SeoPlanSubscriptionMapper seoPlanSubscriptionMapper;
 
     @Resource private SeoKeywordsMapper seoKeywordsMapper;
 
     @Autowired private ISeoKeywordsService seoKeywordsService;
 
+    @Autowired private ISeoKeywordsSerpService seoKeywordsSerpService;
+
     @Autowired private ISeoPlanSubscriptionService seoPlanSubscriptionService;
 
     @Autowired private IHistoryReachStandardSiteService historyReachStandardSiteService;
@@ -75,7 +80,7 @@ public class SearchKeywordsServiceImpl implements ISearchKeywordsService {
                 continue;
             }
             if ("APPOINT_KEYWORDS".equals(kpiStatistics.getKpiCode())) {
-                Integer standard = seoMarketPlanMapper.getKeywordStandard(siteCode);
+                Integer standard = seoPlanSubscriptionMapper.getKeywordStandard(siteCode);
                 String datesStr = "";
                 List<String> dateList =
                         seoKeywordsService.getKeywordsLastSevenDays(siteCode, 1, historyId);
@@ -150,12 +155,12 @@ public class SearchKeywordsServiceImpl implements ISearchKeywordsService {
     @Override
     public Map getRankInfo(String siteCode, String historyId) throws ParseException {
         List<SeoRankInfoVO> seoRankInfos = this.getSeoRankInfo(siteCode, historyId);
-        ServerTimeVO ServerTimeVO = this.getServerTimeVO(siteCode, historyId);
+        ServerTimeVO ServerTimeVO = this.getServerTime(siteCode, historyId);
 
         Map map = new HashMap<>();
         map.put("appointKeyword", seoRankInfos.get(0));
         map.put("longTailKeyword", seoRankInfos.get(1));
-        map.put("ServerTimeVO", ServerTimeVO);
+        map.put("ServerTime", ServerTimeVO);
         return map;
     }
 
@@ -209,7 +214,7 @@ public class SearchKeywordsServiceImpl implements ISearchKeywordsService {
      * @param historyId 营销方案id
      * @return 服务情况,达标时间以及剩余时间
      */
-    private ServerTimeVO getServerTimeVO(String siteCode, String historyId) {
+    private ServerTimeVO getServerTime(String siteCode, String historyId) {
         ServerTimeVO ServerTimeVO = new ServerTimeVO();
 
         // 获取套餐
@@ -227,7 +232,8 @@ public class SearchKeywordsServiceImpl implements ISearchKeywordsService {
         // 达成时间
         Date achieveTime = history.getKeywordsAchieveTime();
         if (achieveTime != null) {
-            ServerTimeVO.setReachStandardTime(new SimpleDateFormat(DateUtil.DATE_PATTERN).format(achieveTime));
+            ServerTimeVO.setReachStandardTime(
+                    new SimpleDateFormat(DateUtil.DATE_PATTERN).format(achieveTime));
         }
 
         // 达成天数
@@ -239,12 +245,14 @@ public class SearchKeywordsServiceImpl implements ISearchKeywordsService {
             List<HistoryReachStandardSite> historyReachStandardSiteList =
                     historyReachStandardSiteService.list(historyReachStandardSiteQueryWrapper);
             if (ListUtil.isEmpty(historyReachStandardSiteList)) {
-                reachStandardDays = DateUtil.diffDay(achieveTime, new Date());
+                reachStandardDays = (int) DateUtil.diffDays(achieveTime, new Date());
             } else {
                 HistoryReachStandardSite historyReachStandardSite =
                         historyReachStandardSiteList.get(0);
                 int newDays =
-                        DateUtil.diffDay(historyReachStandardSite.getCreateTime(), new Date());
+                        (int)
+                                DateUtil.diffDays(
+                                        historyReachStandardSite.getCreateTime(), new Date());
                 reachStandardDays = historyReachStandardSite.getReachStandardDays() + newDays;
             }
         }
@@ -259,14 +267,14 @@ public class SearchKeywordsServiceImpl implements ISearchKeywordsService {
             int compensateDay = history.getCompensateDay();
             int totalGiveAndCompensateDay = giveDay + compensateDay;
             log.info(
-                    "getServerTimeVO -- historyId:{},giveDay:{},compensateDay:{},totalGiveAndCompensateDay:{}",
+                    "getServerTime -- historyId:{},giveDay:{},compensateDay:{},totalGiveAndCompensateDay:{}",
                     history.getId(),
                     giveDay,
                     compensateDay,
                     totalGiveAndCompensateDay);
             remainServerDays = serverDay + totalGiveAndCompensateDay - reachStandardDays;
             log.info(
-                    "getServerTimeVO -- 剩余服务天数:{},服务天数:{},赠、补天数:{},达成天数:{}",
+                    "getServerTime -- 剩余服务天数:{},服务天数:{},赠、补天数:{},达成天数:{}",
                     remainServerDays,
                     serverDay,
                     totalGiveAndCompensateDay,
@@ -279,27 +287,27 @@ public class SearchKeywordsServiceImpl implements ISearchKeywordsService {
             int compensateDay = history.getCompensateDay();
             int totalGiveAndCompensateDay = giveDay + compensateDay;
             log.info(
-                    "getServerTimeVO -- historyId:{},giveDay:{},compensateDay:{},totalGiveAndCompensateDay:{}",
+                    "getServerTime -- historyId:{},giveDay:{},compensateDay:{},totalGiveAndCompensateDay:{}",
                     history.getId(),
                     giveDay,
                     compensateDay,
                     totalGiveAndCompensateDay);
             Date serverEndTime = history.getServiceEndTime();
             log.info(
-                    "getServerTimeVO -- 原来的serverEndTime:{}",
+                    "getServerTime -- 原来的serverEndTime:{}",
                     new SimpleDateFormat(DateUtil.DATE_PATTERN).format(serverEndTime));
-            serverEndTime = DateUtil.addDate(serverEndTime, totalGiveAndCompensateDay, 3);
+            serverEndTime = DateUtil.addDays(serverEndTime, totalGiveAndCompensateDay);
             log.info(
-                    "getServerTimeVO -- 增加赠、补天数:{},赠送天数、补偿天数后的serverEndTime:{}",
+                    "getServerTime -- 增加赠、补天数:{},赠送天数、补偿天数后的serverEndTime:{}",
                     totalGiveAndCompensateDay,
                     new SimpleDateFormat(DateUtil.DATE_PATTERN).format(serverEndTime));
             if (serverEndTime.compareTo(new Date()) <= 0) {
                 remainServerDays = 0;
             } else {
-                remainServerDays = DateUtil.diffDay(serverEndTime, new Date());
+                remainServerDays = (int) DateUtil.diffDays(serverEndTime, new Date());
             }
             log.info(
-                    "getServerTimeVO -- 剩余服务天数:{},赠、补天数:{},达成天数:{}",
+                    "getServerTime -- 剩余服务天数:{},赠、补天数:{},达成天数:{}",
                     remainServerDays,
                     totalGiveAndCompensateDay,
                     reachStandardDays);
@@ -356,4 +364,108 @@ public class SearchKeywordsServiceImpl implements ISearchKeywordsService {
         }
         return KeywordsRankMap;
     }
+
+    /**
+     * 给列表中的关键字增加排名信息
+     * 根据关键词类型
+     * @param keywordList 关键词列表
+     *
+     */
+    @Override
+    public void addRankInfoByIntervalTimeByType(List<SeoKeywords> keywordList, Integer keywordType, String siteCode, String historyId, List<String> dateList) throws Exception {
+        if (ListUtil.isEmpty(keywordList)) {
+            return;
+        }
+
+        String datesStr = "";
+        if(ListUtil.isEmpty(dateList)){
+            return;
+        }else{
+            for(int i = 0; i < dateList.size(); i++){
+                if(i == dateList.size() - 1){
+                    datesStr +=  "'" + dateList.get(i) + "'";
+                }else{
+                    datesStr +=  "'" + dateList.get(i) + "'" + ",";
+                }
+            }
+            datesStr = "(" + datesStr + ")";
+        }
+        List<Integer> keywordIds = keywordList.stream().map(SeoKeywords::getId).collect(Collectors.toList());
+        List<SeoKeywordsSerp> serpList = seoKeywordsSerpService.list(new LambdaQueryWrapper<SeoKeywordsSerp>()
+                .in(SeoKeywordsSerp::getKeywordsId, keywordIds)
+                .in(SeoKeywordsSerp::getSeDate, dateList));
+        List<SeoKeywordsSerp> noRepeatSerpList = new ArrayList<>();
+        Map<String, Integer> serpMap = new HashMap<>();
+        if(ListUtil.notEmpty(serpList)){
+            for (SeoKeywordsSerp seoKeywordsSerp : serpList) {
+                seoKeywordsSerp.setKey(seoKeywordsSerp.getKeywordsId() + "_" + seoKeywordsSerp.getSeDate());
+                if(ListUtil.notEmpty(noRepeatSerpList)){
+                    List<SeoKeywordsSerp> have = noRepeatSerpList.stream().filter(o -> o.getKey().equals(seoKeywordsSerp.getKey())).collect(Collectors.toList());
+                    if(ListUtil.isEmpty(have)){
+                        serpMap.put(seoKeywordsSerp.getKey(),seoKeywordsSerp.getRankAbsolute());
+                        noRepeatSerpList.add(seoKeywordsSerp);
+                    }else{
+                        log.info("重复的数据:" + seoKeywordsSerp.getKey());
+                    }
+                }else {
+                    serpMap.put(seoKeywordsSerp.getKey(),seoKeywordsSerp.getRankAbsolute());
+                    noRepeatSerpList.add(seoKeywordsSerp);
+                }
+            }
+        }
+
+        for (SeoKeywords keyword : keywordList) {
+            Map<String, String> rankInfo = new LinkedHashMap<>();
+            for (String date : dateList) {
+
+                // 从Map中获取那天的排名信息
+                Integer rankAbsolute = serpMap.get(keyword.getId() + "_" + date);
+
+                if(rankAbsolute == null){
+                    rankAbsolute = 0;
+                }
+                rankInfo.put(date, rankAbsolute + "");
+            }
+
+            keyword.setRankInfo(rankInfo);
+            keyword.setIpAddress("223.112.18.226");
+
+            keyword.setDateList(dateList);
+            if(StringUtil.isEmpty(keyword.getSearchUrl())){
+                keyword.setSearchUrl("https://www.google.com/");
+            }
+        }
+    }
+
+    /**
+     * 自适应宽度(中文支持)
+     * @param sheet
+     * @param size 因为for循环从0开始,size值为 列数-1
+     */
+    @Override
+    public void setSizeColumn(Sheet sheet, int size) {
+        for (int columnNum = 0; columnNum <= size; columnNum++) {
+            int columnWidth = sheet.getColumnWidth(columnNum) / 256;
+            for (int rowNum = 0; rowNum <= sheet.getLastRowNum(); rowNum++) {
+                Row currentRow;
+                //当前行未被使用过
+                if (sheet.getRow(rowNum) == null) {
+                    currentRow = sheet.createRow(rowNum);
+                } else {
+                    currentRow = sheet.getRow(rowNum);
+                }
+
+                if (currentRow.getCell(columnNum) != null) {
+                    Cell currentCell = currentRow.getCell(columnNum);
+                    if (currentCell.getCellType() == CellType.STRING) {
+                        int length = currentCell.getStringCellValue().getBytes().length;
+                        if (columnWidth < length) {
+                            columnWidth = length;
+                        }
+                    }
+                }
+            }
+            sheet.setColumnWidth(columnNum, columnWidth * 256);
+        }
+    }
 }

+ 49 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/service/impl/SeoKeywordsServiceImpl.java

@@ -1,15 +1,18 @@
 package org.jeecg.modules.adweb.serp.service.impl;
 
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 
 import jakarta.annotation.Resource;
 
+import org.jeecg.modules.adweb.common.util.ListUtil;
 import org.jeecg.modules.adweb.serp.entity.SeoKeywords;
 import org.jeecg.modules.adweb.serp.mapper.SeoKeywordsMapper;
 import org.jeecg.modules.adweb.serp.service.ISeoKeywordsService;
 import org.jeecg.modules.adweb.serp.vo.RankInfoVO;
 import org.springframework.stereotype.Service;
 
+import java.text.ParseException;
 import java.util.List;
 
 /**
@@ -48,4 +51,50 @@ public class SeoKeywordsServiceImpl extends ServiceImpl<SeoKeywordsMapper, SeoKe
         //指定词
         return seoKeywordsMapper.queryKeywordNumByRankRange(siteCode, historyId,rankStart,rankEnd,dateStr,keywordType);
     }
+
+    /**
+     * 获取关键词列表
+     * @return 关键词列表
+     */
+    @Override
+    public IPage<SeoKeywords> getKeywordList(IPage<SeoKeywords> page,
+                                             Integer rankStart,
+                                             Integer rankEnd,
+                                             String keyword,
+                                             String siteCode,
+                                             Integer keywordType,
+                                             boolean reachStandard,
+                                             String historyId,
+                                             String column,
+                                             String order,
+                                             String buttonColumn,
+                                             String buttonSort,
+                                             List<String> dateList) throws ParseException {
+        if (reachStandard) {
+            rankStart = 1;
+            int standard = 10;
+            if (keywordType != null && keywordType == 1) {
+                standard = seoKeywordsMapper.getKeywordStandard(siteCode);
+            }
+            rankEnd = standard;
+        }
+
+        boolean isCustomer = true;
+
+        String datesStr = "";
+        if(ListUtil.isEmpty(dateList)){
+            return null;
+        }else{
+            for(int i = 0; i < dateList.size(); i++){
+                if(i == dateList.size() - 1){
+                    datesStr +=  "'" + dateList.get(i) + "'";
+                }else{
+                    datesStr +=  "'" + dateList.get(i) + "'" + ",";
+                }
+            }
+            datesStr = "(" + datesStr + ")";
+        }
+
+        return seoKeywordsMapper.getKeywordList(page, rankStart, rankEnd, isCustomer, keyword, siteCode, keywordType, datesStr, historyId,column,order,buttonColumn,buttonSort);
+    }
 }

+ 0 - 19
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/adweb/serp/service/impl/SeoMarketPlanServiceImpl.java

@@ -1,19 +0,0 @@
-package org.jeecg.modules.adweb.serp.service.impl;
-
-import org.jeecg.modules.adweb.serp.entity.SeoMarketPlan;
-import org.jeecg.modules.adweb.serp.mapper.SeoMarketPlanMapper;
-import org.jeecg.modules.adweb.serp.service.ISeoMarketPlanService;
-import org.springframework.stereotype.Service;
-
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-
-/**
- * @Description: 营销方案
- * @Author: jeecg-boot
- * @Date:   2024-10-15
- * @Version: V1.0
- */
-@Service
-public class SeoMarketPlanServiceImpl extends ServiceImpl<SeoMarketPlanMapper, SeoMarketPlan> implements ISeoMarketPlanService {
-
-}

+ 63 - 0
jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysBaseApiImpl.java

@@ -10,6 +10,7 @@ import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.google.common.base.Joiner;
+import com.xkcoding.http.util.StringUtil;
 import freemarker.core.TemplateClassResolver;
 import freemarker.template.Configuration;
 import freemarker.template.Template;
@@ -40,7 +41,12 @@ import org.jeecg.common.util.oConvertUtils;
 import org.jeecg.config.firewall.SqlInjection.IDictTableWhiteListHandler;
 import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
 import org.jeecg.config.security.utils.SecureUtil;
+import org.jeecg.modules.adweb.common.constant.AdwebConstant;
+import org.jeecg.modules.adweb.common.constant.NumConstant;
 import org.jeecg.modules.adweb.common.util.ListUtil;
+import org.jeecg.modules.adweb.site.entity.AdwebSite;
+import org.jeecg.modules.adweb.site.service.IAdwebSiteService;
+import org.jeecg.modules.adweb.site.service.ISiteUserPermissionService;
 import org.jeecg.modules.message.entity.SysMessageTemplate;
 import org.jeecg.modules.message.handle.impl.DdSendMsgHandle;
 import org.jeecg.modules.message.handle.impl.EmailSendMsgHandle;
@@ -137,6 +143,10 @@ public class SysBaseApiImpl implements ISysBaseAPI {
 	private ISysUserPositionService sysUserPositionService;
 
 	@Autowired
+	private ISiteUserPermissionService siteUserPermissionService;
+	@Autowired
+	private IAdwebSiteService adwebSiteService;
+	@Autowired
 	private IDictTableWhiteListHandler dictTableWhiteListHandler;
 
 	@Override
@@ -1926,4 +1936,57 @@ public class SysBaseApiImpl implements ISysBaseAPI {
 		list.add(sysUser.getId());
 		return list;
 	}
+
+	@Override
+	public boolean isNotOwnSite(Integer siteId) {
+		if(siteId == null){
+			return true;
+		}
+		QueryWrapper<AdwebSite> queryWrapper = new QueryWrapper<>();
+		LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
+		if (this.isOem()){
+			List<String> oemGroupUids = this.getOemGroupUids();
+			List<String> codeList = siteUserPermissionService.getSiteCodeListByUids(oemGroupUids);
+			queryWrapper.in("code", codeList);
+		}else if (!this.isAdmin()) {
+			LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
+			List<String> codeList = siteUserPermissionService.getSiteCodeList(loginUser.getId());
+			queryWrapper.in("code", codeList);
+		}
+		queryWrapper.eq("id", siteId);
+		queryWrapper.ne("status", NumConstant.ZERO);
+		List<AdwebSite> list = adwebSiteService.list(queryWrapper);
+		if (ListUtil.notEmpty(list)) {
+			return false;
+		}
+		return true;
+	}
+
+	@Override
+	public boolean isNotOwnSite(String siteCode) {
+		if (this.isAdmin()) {
+			return false;
+		}
+		if(StringUtil.isEmpty(siteCode)){
+			return true;
+		}
+		QueryWrapper<AdwebSite> queryWrapper = new QueryWrapper<>();
+		LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
+		if (this.isOem()){
+			List<String> oemGroupUids = this.getOemGroupUids();
+			List<String> codeList = siteUserPermissionService.getSiteCodeListByUids(oemGroupUids);
+			queryWrapper.in("code", codeList);
+		} else if (!this.isAdmin()) {
+			LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
+			List<String> codeList = siteUserPermissionService.getSiteCodeList(loginUser.getId());
+			queryWrapper.in("code", codeList);
+		}
+		queryWrapper.eq("code", siteCode);
+		queryWrapper.ne("status", AdwebConstant.SITE_DEL);
+		List<AdwebSite> list = adwebSiteService.list(queryWrapper);
+		if (ListUtil.notEmpty(list)) {
+			return false;
+		}
+		return true;
+	}
 }