feat: 新增虚拟支付订单与网盘链接检测功能
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
package com.ruoyi.office.config;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* 网盘检测线程池。限制并发数,避免批量检测时触发平台风控。
|
||||
*/
|
||||
@Configuration
|
||||
public class NetDiskCheckExecutorConfig
|
||||
{
|
||||
@Bean(name = "netDiskCheckExecutor", destroyMethod = "shutdown")
|
||||
public ExecutorService netDiskCheckExecutor()
|
||||
{
|
||||
AtomicInteger threadNumber = new AtomicInteger(1);
|
||||
ThreadFactory threadFactory = runnable ->
|
||||
{
|
||||
Thread thread = new Thread(runnable,
|
||||
"net-disk-check-" + threadNumber.getAndIncrement());
|
||||
thread.setDaemon(true);
|
||||
return thread;
|
||||
};
|
||||
return Executors.newFixedThreadPool(4, threadFactory);
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import javax.servlet.http.HttpServletResponse;
|
||||
import com.ruoyi.common.utils.CoverGenerator;
|
||||
import com.ruoyi.office.domain.TtCode;
|
||||
import com.ruoyi.office.service.ITtCodeService;
|
||||
import com.ruoyi.office.service.IProjectLinkCheckService;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@@ -42,6 +43,8 @@ public class TtProjectInfoController extends BaseController {
|
||||
private ITtProjectInfoService ttProjectInfoService;
|
||||
@Autowired
|
||||
private ITtCodeService ttCodeService;
|
||||
@Autowired
|
||||
private IProjectLinkCheckService projectLinkCheckService;
|
||||
|
||||
|
||||
/**
|
||||
@@ -76,6 +79,26 @@ public class TtProjectInfoController extends BaseController {
|
||||
return success(ttProjectInfoService.selectTtProjectInfoById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测单个项目的网盘链接。
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('office:project:edit')")
|
||||
@Log(title = "检测项目网盘链接", businessType = BusinessType.OTHER)
|
||||
@PostMapping("/link-check/single/{id}")
|
||||
public AjaxResult checkProjectLink(@PathVariable("id") Integer id) {
|
||||
return success(projectLinkCheckService.checkProject(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测选中项目的网盘链接。
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('office:project:edit')")
|
||||
@Log(title = "批量检测项目网盘链接", businessType = BusinessType.OTHER)
|
||||
@PostMapping("/link-check/batch")
|
||||
public AjaxResult checkProjectLinks(@RequestBody Integer[] ids) {
|
||||
return success(projectLinkCheckService.checkProjects(ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增项目清单
|
||||
*/
|
||||
|
||||
@@ -4,6 +4,7 @@ import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 项目清单对象 tt_project_info
|
||||
@@ -50,6 +51,24 @@ public class TtProjectInfo extends BaseEntity
|
||||
@Excel(name = "项目百度链接")
|
||||
private String projectBaiduUrl;
|
||||
|
||||
/** 夸克网盘最近检测状态 */
|
||||
private String quarkCheckStatus;
|
||||
|
||||
/** 夸克网盘最近检测说明 */
|
||||
private String quarkCheckMessage;
|
||||
|
||||
/** 夸克网盘最近检测时间 */
|
||||
private Date quarkCheckedAt;
|
||||
|
||||
/** 百度网盘最近检测状态 */
|
||||
private String baiduCheckStatus;
|
||||
|
||||
/** 百度网盘最近检测说明 */
|
||||
private String baiduCheckMessage;
|
||||
|
||||
/** 百度网盘最近检测时间 */
|
||||
private Date baiduCheckedAt;
|
||||
|
||||
public void setId(Integer id)
|
||||
{
|
||||
this.id = id;
|
||||
@@ -131,6 +150,54 @@ public class TtProjectInfo extends BaseEntity
|
||||
this.projectBaiduUrl = projectBaiduUrl;
|
||||
}
|
||||
|
||||
public String getQuarkCheckStatus() {
|
||||
return quarkCheckStatus;
|
||||
}
|
||||
|
||||
public void setQuarkCheckStatus(String quarkCheckStatus) {
|
||||
this.quarkCheckStatus = quarkCheckStatus;
|
||||
}
|
||||
|
||||
public String getQuarkCheckMessage() {
|
||||
return quarkCheckMessage;
|
||||
}
|
||||
|
||||
public void setQuarkCheckMessage(String quarkCheckMessage) {
|
||||
this.quarkCheckMessage = quarkCheckMessage;
|
||||
}
|
||||
|
||||
public Date getQuarkCheckedAt() {
|
||||
return quarkCheckedAt;
|
||||
}
|
||||
|
||||
public void setQuarkCheckedAt(Date quarkCheckedAt) {
|
||||
this.quarkCheckedAt = quarkCheckedAt;
|
||||
}
|
||||
|
||||
public String getBaiduCheckStatus() {
|
||||
return baiduCheckStatus;
|
||||
}
|
||||
|
||||
public void setBaiduCheckStatus(String baiduCheckStatus) {
|
||||
this.baiduCheckStatus = baiduCheckStatus;
|
||||
}
|
||||
|
||||
public String getBaiduCheckMessage() {
|
||||
return baiduCheckMessage;
|
||||
}
|
||||
|
||||
public void setBaiduCheckMessage(String baiduCheckMessage) {
|
||||
this.baiduCheckMessage = baiduCheckMessage;
|
||||
}
|
||||
|
||||
public Date getBaiduCheckedAt() {
|
||||
return baiduCheckedAt;
|
||||
}
|
||||
|
||||
public void setBaiduCheckedAt(Date baiduCheckedAt) {
|
||||
this.baiduCheckedAt = baiduCheckedAt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||
@@ -141,6 +208,7 @@ public class TtProjectInfo extends BaseEntity
|
||||
.append("projectName1", getProjectName1())
|
||||
.append("projectDesc", getProjectDesc())
|
||||
.append("projectUrl", getProjectUrl())
|
||||
.append("projectBaiduUrl", getProjectBaiduUrl())
|
||||
.append("projectVurl", getProjectVurl())
|
||||
.toString();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
package com.ruoyi.office.domain;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 项目网盘链接检测结果对象 tt_project_link_check。
|
||||
*/
|
||||
public class TtProjectLinkCheck
|
||||
{
|
||||
private Long id;
|
||||
|
||||
private Integer projectId;
|
||||
|
||||
private String diskType;
|
||||
|
||||
private String linkUrl;
|
||||
|
||||
private String checkStatus;
|
||||
|
||||
private String providerCode;
|
||||
|
||||
private String checkMessage;
|
||||
|
||||
private Long responseTimeMs;
|
||||
|
||||
private Date checkedAt;
|
||||
|
||||
public Long getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Integer getProjectId()
|
||||
{
|
||||
return projectId;
|
||||
}
|
||||
|
||||
public void setProjectId(Integer projectId)
|
||||
{
|
||||
this.projectId = projectId;
|
||||
}
|
||||
|
||||
public String getDiskType()
|
||||
{
|
||||
return diskType;
|
||||
}
|
||||
|
||||
public void setDiskType(String diskType)
|
||||
{
|
||||
this.diskType = diskType;
|
||||
}
|
||||
|
||||
public String getLinkUrl()
|
||||
{
|
||||
return linkUrl;
|
||||
}
|
||||
|
||||
public void setLinkUrl(String linkUrl)
|
||||
{
|
||||
this.linkUrl = linkUrl;
|
||||
}
|
||||
|
||||
public String getCheckStatus()
|
||||
{
|
||||
return checkStatus;
|
||||
}
|
||||
|
||||
public void setCheckStatus(String checkStatus)
|
||||
{
|
||||
this.checkStatus = checkStatus;
|
||||
}
|
||||
|
||||
public String getProviderCode()
|
||||
{
|
||||
return providerCode;
|
||||
}
|
||||
|
||||
public void setProviderCode(String providerCode)
|
||||
{
|
||||
this.providerCode = providerCode;
|
||||
}
|
||||
|
||||
public String getCheckMessage()
|
||||
{
|
||||
return checkMessage;
|
||||
}
|
||||
|
||||
public void setCheckMessage(String checkMessage)
|
||||
{
|
||||
this.checkMessage = checkMessage;
|
||||
}
|
||||
|
||||
public Long getResponseTimeMs()
|
||||
{
|
||||
return responseTimeMs;
|
||||
}
|
||||
|
||||
public void setResponseTimeMs(Long responseTimeMs)
|
||||
{
|
||||
this.responseTimeMs = responseTimeMs;
|
||||
}
|
||||
|
||||
public Date getCheckedAt()
|
||||
{
|
||||
return checkedAt;
|
||||
}
|
||||
|
||||
public void setCheckedAt(Date checkedAt)
|
||||
{
|
||||
this.checkedAt = checkedAt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.ruoyi.office.mapper;
|
||||
|
||||
import com.ruoyi.office.domain.TtProjectLinkCheck;
|
||||
|
||||
/**
|
||||
* 项目网盘链接检测结果 Mapper。
|
||||
*/
|
||||
public interface TtProjectLinkCheckMapper
|
||||
{
|
||||
int upsertTtProjectLinkCheck(TtProjectLinkCheck linkCheck);
|
||||
|
||||
int deleteByProjectId(Integer projectId);
|
||||
|
||||
int deleteByProjectIds(Integer[] projectIds);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.ruoyi.office.service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 项目网盘链接检测服务。
|
||||
*/
|
||||
public interface IProjectLinkCheckService
|
||||
{
|
||||
Map<String, Object> checkProject(Integer projectId);
|
||||
|
||||
Map<String, Object> checkProjects(Integer[] projectIds);
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
package com.ruoyi.office.service.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.office.domain.TtProjectInfo;
|
||||
import com.ruoyi.office.domain.TtProjectLinkCheck;
|
||||
import com.ruoyi.office.mapper.TtProjectInfoMapper;
|
||||
import com.ruoyi.office.mapper.TtProjectLinkCheckMapper;
|
||||
import com.ruoyi.office.service.IProjectLinkCheckService;
|
||||
import com.ruoyi.office.service.netdisk.NetDiskCheckResult;
|
||||
import com.ruoyi.office.service.netdisk.NetDiskConstants;
|
||||
import com.ruoyi.office.service.netdisk.NetDiskLinkChecker;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 项目网盘链接检测服务实现。
|
||||
*/
|
||||
@Service
|
||||
public class ProjectLinkCheckServiceImpl implements IProjectLinkCheckService
|
||||
{
|
||||
private static final int MAX_BATCH_SIZE = 20;
|
||||
private static final int MAX_MESSAGE_LENGTH = 250;
|
||||
|
||||
private final TtProjectInfoMapper projectInfoMapper;
|
||||
private final TtProjectLinkCheckMapper linkCheckMapper;
|
||||
private final Map<String, NetDiskLinkChecker> checkerMap;
|
||||
private final ExecutorService netDiskCheckExecutor;
|
||||
|
||||
public ProjectLinkCheckServiceImpl(
|
||||
TtProjectInfoMapper projectInfoMapper,
|
||||
TtProjectLinkCheckMapper linkCheckMapper,
|
||||
List<NetDiskLinkChecker> checkers,
|
||||
@Qualifier("netDiskCheckExecutor") ExecutorService netDiskCheckExecutor)
|
||||
{
|
||||
this.projectInfoMapper = projectInfoMapper;
|
||||
this.linkCheckMapper = linkCheckMapper;
|
||||
this.netDiskCheckExecutor = netDiskCheckExecutor;
|
||||
this.checkerMap = new LinkedHashMap<>();
|
||||
for (NetDiskLinkChecker checker : checkers)
|
||||
{
|
||||
this.checkerMap.put(checker.getDiskType(), checker);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> checkProject(Integer projectId)
|
||||
{
|
||||
if (projectId == null)
|
||||
{
|
||||
throw new ServiceException("项目编号不能为空");
|
||||
}
|
||||
ProjectCheckOutcome outcome = checkProjectInternal(projectId);
|
||||
return buildSummary(Collections.singletonList(outcome));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> checkProjects(Integer[] projectIds)
|
||||
{
|
||||
if (projectIds == null || projectIds.length == 0)
|
||||
{
|
||||
throw new ServiceException("请至少选择一个项目");
|
||||
}
|
||||
|
||||
Set<Integer> uniqueIds = new LinkedHashSet<>();
|
||||
for (Integer projectId : projectIds)
|
||||
{
|
||||
if (projectId != null)
|
||||
{
|
||||
uniqueIds.add(projectId);
|
||||
}
|
||||
}
|
||||
if (uniqueIds.isEmpty())
|
||||
{
|
||||
throw new ServiceException("请至少选择一个项目");
|
||||
}
|
||||
if (uniqueIds.size() > MAX_BATCH_SIZE)
|
||||
{
|
||||
throw new ServiceException("一次最多检测 " + MAX_BATCH_SIZE + " 个项目");
|
||||
}
|
||||
|
||||
List<CompletableFuture<ProjectCheckOutcome>> futures = new ArrayList<>();
|
||||
for (Integer projectId : uniqueIds)
|
||||
{
|
||||
futures.add(CompletableFuture.supplyAsync(
|
||||
() -> checkProjectInternal(projectId), netDiskCheckExecutor));
|
||||
}
|
||||
|
||||
List<ProjectCheckOutcome> outcomes = new ArrayList<>();
|
||||
for (CompletableFuture<ProjectCheckOutcome> future : futures)
|
||||
{
|
||||
outcomes.add(future.join());
|
||||
}
|
||||
return buildSummary(outcomes);
|
||||
}
|
||||
|
||||
private ProjectCheckOutcome checkProjectInternal(Integer projectId)
|
||||
{
|
||||
TtProjectInfo project = projectInfoMapper.selectTtProjectInfoById(projectId);
|
||||
if (project == null)
|
||||
{
|
||||
throw new ServiceException("项目不存在:" + projectId);
|
||||
}
|
||||
|
||||
List<NetDiskCheckResult> results = new ArrayList<>(2);
|
||||
checkAndSave(projectId, project.getProjectUrl(), NetDiskConstants.DISK_QUARK, results);
|
||||
checkAndSave(projectId, project.getProjectBaiduUrl(), NetDiskConstants.DISK_BAIDU, results);
|
||||
return new ProjectCheckOutcome(project.getId(), project.getProjectNum(), results);
|
||||
}
|
||||
|
||||
private void checkAndSave(Integer projectId, String linkUrl, String diskType,
|
||||
List<NetDiskCheckResult> results)
|
||||
{
|
||||
if (StringUtils.isBlank(linkUrl))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NetDiskLinkChecker checker = checkerMap.get(diskType);
|
||||
NetDiskCheckResult result;
|
||||
if (checker == null)
|
||||
{
|
||||
result = new NetDiskCheckResult(diskType, linkUrl,
|
||||
NetDiskConstants.STATUS_UNKNOWN, "NO_CHECKER",
|
||||
"未找到对应的网盘检测器", 0L);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = checker.check(linkUrl);
|
||||
}
|
||||
|
||||
TtProjectLinkCheck linkCheck = new TtProjectLinkCheck();
|
||||
linkCheck.setProjectId(projectId);
|
||||
linkCheck.setDiskType(diskType);
|
||||
linkCheck.setLinkUrl(linkUrl);
|
||||
linkCheck.setCheckStatus(result.getStatus());
|
||||
linkCheck.setProviderCode(truncate(result.getProviderCode(), 32));
|
||||
linkCheck.setCheckMessage(truncate(result.getMessage(), MAX_MESSAGE_LENGTH));
|
||||
linkCheck.setResponseTimeMs(result.getResponseTimeMs());
|
||||
linkCheck.setCheckedAt(new Date());
|
||||
linkCheckMapper.upsertTtProjectLinkCheck(linkCheck);
|
||||
results.add(result);
|
||||
}
|
||||
|
||||
private Map<String, Object> buildSummary(List<ProjectCheckOutcome> outcomes)
|
||||
{
|
||||
int validCount = 0;
|
||||
int invalidCount = 0;
|
||||
int warningCount = 0;
|
||||
int unknownCount = 0;
|
||||
List<Map<String, Object>> resultItems = new ArrayList<>();
|
||||
|
||||
for (ProjectCheckOutcome outcome : outcomes)
|
||||
{
|
||||
for (NetDiskCheckResult result : outcome.results)
|
||||
{
|
||||
if (NetDiskConstants.STATUS_VALID.equals(result.getStatus()))
|
||||
{
|
||||
validCount++;
|
||||
}
|
||||
else if (NetDiskConstants.STATUS_INVALID.equals(result.getStatus()))
|
||||
{
|
||||
invalidCount++;
|
||||
}
|
||||
else if (NetDiskConstants.STATUS_UNKNOWN.equals(result.getStatus()))
|
||||
{
|
||||
unknownCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
warningCount++;
|
||||
}
|
||||
|
||||
Map<String, Object> item = new LinkedHashMap<>();
|
||||
item.put("projectId", outcome.projectId);
|
||||
item.put("projectNum", outcome.projectNum);
|
||||
item.put("diskType", result.getDiskType());
|
||||
item.put("status", result.getStatus());
|
||||
item.put("message", result.getMessage());
|
||||
resultItems.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Object> summary = new LinkedHashMap<>();
|
||||
summary.put("projectCount", outcomes.size());
|
||||
summary.put("linkCount", resultItems.size());
|
||||
summary.put("validCount", validCount);
|
||||
summary.put("invalidCount", invalidCount);
|
||||
summary.put("warningCount", warningCount);
|
||||
summary.put("unknownCount", unknownCount);
|
||||
summary.put("results", resultItems);
|
||||
return summary;
|
||||
}
|
||||
|
||||
private String truncate(String value, int maxLength)
|
||||
{
|
||||
if (value == null || value.length() <= maxLength)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
return value.substring(0, maxLength);
|
||||
}
|
||||
|
||||
private static class ProjectCheckOutcome
|
||||
{
|
||||
private final Integer projectId;
|
||||
private final String projectNum;
|
||||
private final List<NetDiskCheckResult> results;
|
||||
|
||||
private ProjectCheckOutcome(Integer projectId, String projectNum,
|
||||
List<NetDiskCheckResult> results)
|
||||
{
|
||||
this.projectId = projectId;
|
||||
this.projectNum = projectNum;
|
||||
this.results = results;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,10 @@ import java.util.List;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.office.domain.TtCode;
|
||||
import com.ruoyi.office.mapper.TtCodeMapper;
|
||||
import com.ruoyi.office.mapper.TtProjectLinkCheckMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import com.ruoyi.office.mapper.TtProjectInfoMapper;
|
||||
import com.ruoyi.office.domain.TtProjectInfo;
|
||||
import com.ruoyi.office.service.ITtProjectInfoService;
|
||||
@@ -25,6 +27,8 @@ public class TtProjectInfoServiceImpl implements ITtProjectInfoService
|
||||
private TtProjectInfoMapper ttProjectInfoMapper;
|
||||
@Autowired
|
||||
private TtCodeMapper ttCodeMapper;
|
||||
@Autowired
|
||||
private TtProjectLinkCheckMapper ttProjectLinkCheckMapper;
|
||||
|
||||
/**
|
||||
* 查询项目清单
|
||||
@@ -81,8 +85,10 @@ public class TtProjectInfoServiceImpl implements ITtProjectInfoService
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public int deleteTtProjectInfoByIds(Integer[] ids)
|
||||
{
|
||||
ttProjectLinkCheckMapper.deleteByProjectIds(ids);
|
||||
return ttProjectInfoMapper.deleteTtProjectInfoByIds(ids);
|
||||
}
|
||||
|
||||
@@ -93,8 +99,10 @@ public class TtProjectInfoServiceImpl implements ITtProjectInfoService
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public int deleteTtProjectInfoById(Integer id)
|
||||
{
|
||||
ttProjectLinkCheckMapper.deleteByProjectId(id);
|
||||
return ttProjectInfoMapper.deleteTtProjectInfoById(id);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
package com.ruoyi.office.service.netdisk;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 百度网盘分享链接检测器。
|
||||
*
|
||||
* 这里只检测分享是否存在,不下载分享文件。
|
||||
*/
|
||||
@Component
|
||||
public class BaiduNetDiskLinkChecker implements NetDiskLinkChecker
|
||||
{
|
||||
private static final String USER_AGENT =
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
|
||||
+ "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131 Safari/537.36";
|
||||
private static final int MAX_REDIRECTS = 5;
|
||||
private static final Set<String> ALLOWED_HOSTS =
|
||||
new HashSet<>(Arrays.asList("pan.baidu.com", "yun.baidu.com"));
|
||||
private static final String[] INVALID_MARKERS = {
|
||||
"页面不存在",
|
||||
"你所访问的页面不存在了",
|
||||
"分享的文件已经被取消了",
|
||||
"分享已过期",
|
||||
"该分享文件已过期",
|
||||
"啊哦,你来晚了"
|
||||
};
|
||||
private static final String[] RISK_MARKERS = {
|
||||
"访问过于频繁",
|
||||
"请输入验证码",
|
||||
"系统繁忙,请稍候再试"
|
||||
};
|
||||
|
||||
private final OkHttpClient httpClient = new OkHttpClient.Builder()
|
||||
.connectTimeout(5, TimeUnit.SECONDS)
|
||||
.readTimeout(8, TimeUnit.SECONDS)
|
||||
.followRedirects(false)
|
||||
.followSslRedirects(false)
|
||||
.build();
|
||||
|
||||
@Override
|
||||
public String getDiskType()
|
||||
{
|
||||
return NetDiskConstants.DISK_BAIDU;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NetDiskCheckResult check(String linkUrl)
|
||||
{
|
||||
long startedAt = System.currentTimeMillis();
|
||||
String url = StringUtils.trim(linkUrl);
|
||||
if (!isAllowedUrl(url) || !hasSharePath(url))
|
||||
{
|
||||
return result(linkUrl, NetDiskConstants.STATUS_FORMAT_ERROR, "FORMAT",
|
||||
"百度网盘链接格式不正确", startedAt);
|
||||
}
|
||||
|
||||
String passcode = getQueryParameter(url, "pwd");
|
||||
String currentUrl = url;
|
||||
try
|
||||
{
|
||||
for (int redirectCount = 0; redirectCount <= MAX_REDIRECTS; redirectCount++)
|
||||
{
|
||||
Request request = new Request.Builder()
|
||||
.url(currentUrl)
|
||||
.header("User-Agent", USER_AGENT)
|
||||
.header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
|
||||
.header("Accept-Encoding", "identity")
|
||||
.get()
|
||||
.build();
|
||||
|
||||
try (Response response = httpClient.newCall(request).execute())
|
||||
{
|
||||
int httpCode = response.code();
|
||||
if (httpCode >= 300 && httpCode < 400)
|
||||
{
|
||||
String location = response.header("Location");
|
||||
if (StringUtils.isBlank(location))
|
||||
{
|
||||
return result(linkUrl, NetDiskConstants.STATUS_UNKNOWN,
|
||||
String.valueOf(httpCode), "百度网盘返回了无目标地址的跳转", startedAt);
|
||||
}
|
||||
String redirectUrl = resolveUrl(currentUrl, location);
|
||||
if (!isAllowedUrl(redirectUrl))
|
||||
{
|
||||
return result(linkUrl, NetDiskConstants.STATUS_UNKNOWN,
|
||||
String.valueOf(httpCode), "百度网盘跳转到了非预期地址", startedAt);
|
||||
}
|
||||
currentUrl = redirectUrl;
|
||||
continue;
|
||||
}
|
||||
|
||||
String body = response.peekBody(1024L * 1024L).string();
|
||||
if (httpCode == 404 || containsAny(body, INVALID_MARKERS))
|
||||
{
|
||||
return result(linkUrl, NetDiskConstants.STATUS_INVALID,
|
||||
String.valueOf(httpCode), "分享已失效、取消或不存在", startedAt);
|
||||
}
|
||||
if (httpCode == 403 || httpCode == 429 || httpCode >= 500 || containsAny(body, RISK_MARKERS))
|
||||
{
|
||||
return result(linkUrl, NetDiskConstants.STATUS_UNKNOWN,
|
||||
String.valueOf(httpCode), "百度网盘暂时拒绝检测或访问受限", startedAt);
|
||||
}
|
||||
if (httpCode >= 200 && httpCode < 300)
|
||||
{
|
||||
boolean needsCode = currentUrl.contains("/share/init");
|
||||
if (needsCode && StringUtils.isBlank(passcode))
|
||||
{
|
||||
return result(linkUrl, NetDiskConstants.STATUS_NEED_CODE,
|
||||
String.valueOf(httpCode), "分享存在,但链接中没有提取码", startedAt);
|
||||
}
|
||||
String message = needsCode
|
||||
? "分享存在,链接中包含提取码"
|
||||
: "分享链接有效";
|
||||
return result(linkUrl, NetDiskConstants.STATUS_VALID,
|
||||
String.valueOf(httpCode), message, startedAt);
|
||||
}
|
||||
return result(linkUrl, NetDiskConstants.STATUS_UNKNOWN,
|
||||
String.valueOf(httpCode), "百度网盘返回了未识别的状态", startedAt);
|
||||
}
|
||||
}
|
||||
return result(linkUrl, NetDiskConstants.STATUS_UNKNOWN, "REDIRECT",
|
||||
"百度网盘跳转次数过多", startedAt);
|
||||
}
|
||||
catch (IOException | RuntimeException e)
|
||||
{
|
||||
return result(linkUrl, NetDiskConstants.STATUS_UNKNOWN, "NETWORK",
|
||||
"检测请求失败:" + safeMessage(e), startedAt);
|
||||
}
|
||||
}
|
||||
|
||||
private NetDiskCheckResult result(String linkUrl, String status, String providerCode,
|
||||
String message, long startedAt)
|
||||
{
|
||||
return new NetDiskCheckResult(getDiskType(), linkUrl, status, providerCode, message,
|
||||
System.currentTimeMillis() - startedAt);
|
||||
}
|
||||
|
||||
private boolean hasSharePath(String url)
|
||||
{
|
||||
try
|
||||
{
|
||||
String path = new URI(url).getPath();
|
||||
return path != null && (path.startsWith("/s/") || path.startsWith("/share/"));
|
||||
}
|
||||
catch (URISyntaxException e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isAllowedUrl(String url)
|
||||
{
|
||||
if (StringUtils.isBlank(url))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
URI uri = new URI(url);
|
||||
return "https".equalsIgnoreCase(uri.getScheme())
|
||||
&& uri.getUserInfo() == null
|
||||
&& (uri.getPort() == -1 || uri.getPort() == 443)
|
||||
&& uri.getHost() != null
|
||||
&& ALLOWED_HOSTS.contains(uri.getHost().toLowerCase());
|
||||
}
|
||||
catch (URISyntaxException e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private String resolveUrl(String baseUrl, String location)
|
||||
{
|
||||
HttpUrl base = HttpUrl.parse(baseUrl);
|
||||
HttpUrl resolved = base == null ? null : base.resolve(location);
|
||||
return resolved == null ? null : resolved.toString();
|
||||
}
|
||||
|
||||
private String getQueryParameter(String url, String name)
|
||||
{
|
||||
HttpUrl httpUrl = HttpUrl.parse(url);
|
||||
return httpUrl == null ? null : httpUrl.queryParameter(name);
|
||||
}
|
||||
|
||||
private boolean containsAny(String body, String[] markers)
|
||||
{
|
||||
if (StringUtils.isBlank(body))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (String marker : markers)
|
||||
{
|
||||
if (body.contains(marker))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private String safeMessage(Exception e)
|
||||
{
|
||||
return StringUtils.defaultIfBlank(e.getMessage(), e.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.ruoyi.office.service.netdisk;
|
||||
|
||||
/**
|
||||
* 单个网盘链接的检测结果。
|
||||
*/
|
||||
public class NetDiskCheckResult
|
||||
{
|
||||
private final String diskType;
|
||||
private final String linkUrl;
|
||||
private final String status;
|
||||
private final String providerCode;
|
||||
private final String message;
|
||||
private final long responseTimeMs;
|
||||
|
||||
public NetDiskCheckResult(String diskType, String linkUrl, String status,
|
||||
String providerCode, String message, long responseTimeMs)
|
||||
{
|
||||
this.diskType = diskType;
|
||||
this.linkUrl = linkUrl;
|
||||
this.status = status;
|
||||
this.providerCode = providerCode;
|
||||
this.message = message;
|
||||
this.responseTimeMs = responseTimeMs;
|
||||
}
|
||||
|
||||
public String getDiskType()
|
||||
{
|
||||
return diskType;
|
||||
}
|
||||
|
||||
public String getLinkUrl()
|
||||
{
|
||||
return linkUrl;
|
||||
}
|
||||
|
||||
public String getStatus()
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
public String getProviderCode()
|
||||
{
|
||||
return providerCode;
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
return message;
|
||||
}
|
||||
|
||||
public long getResponseTimeMs()
|
||||
{
|
||||
return responseTimeMs;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.ruoyi.office.service.netdisk;
|
||||
|
||||
/**
|
||||
* 网盘类型和检测状态常量。
|
||||
*/
|
||||
public final class NetDiskConstants
|
||||
{
|
||||
public static final String DISK_QUARK = "QUARK";
|
||||
public static final String DISK_BAIDU = "BAIDU";
|
||||
|
||||
public static final String STATUS_VALID = "VALID";
|
||||
public static final String STATUS_INVALID = "INVALID";
|
||||
public static final String STATUS_NEED_CODE = "NEED_CODE";
|
||||
public static final String STATUS_CODE_ERROR = "CODE_ERROR";
|
||||
public static final String STATUS_FORMAT_ERROR = "FORMAT_ERROR";
|
||||
public static final String STATUS_UNKNOWN = "UNKNOWN";
|
||||
|
||||
private NetDiskConstants()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.ruoyi.office.service.netdisk;
|
||||
|
||||
/**
|
||||
* 网盘链接检测器。
|
||||
*/
|
||||
public interface NetDiskLinkChecker
|
||||
{
|
||||
String getDiskType();
|
||||
|
||||
NetDiskCheckResult check(String linkUrl);
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
package com.ruoyi.office.service.netdisk;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 夸克网盘分享链接检测器。
|
||||
*/
|
||||
@Component
|
||||
public class QuarkNetDiskLinkChecker implements NetDiskLinkChecker
|
||||
{
|
||||
private static final String TOKEN_API =
|
||||
"https://drive-pc.quark.cn/1/clouddrive/share/sharepage/token"
|
||||
+ "?pr=ucpro&fr=pc&uc_param_str=";
|
||||
private static final String USER_AGENT =
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
|
||||
+ "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131 Safari/537.36";
|
||||
private static final MediaType JSON_MEDIA_TYPE = MediaType.parse("application/json; charset=utf-8");
|
||||
private static final Set<Integer> INVALID_CODES = new HashSet<>(Arrays.asList(
|
||||
41006, 41009, 41010, 41011, 41012, 41019, 41026, 41028, 41029, 41030, 41031
|
||||
));
|
||||
|
||||
private final OkHttpClient httpClient = new OkHttpClient.Builder()
|
||||
.connectTimeout(5, TimeUnit.SECONDS)
|
||||
.readTimeout(8, TimeUnit.SECONDS)
|
||||
.followRedirects(false)
|
||||
.build();
|
||||
|
||||
@Override
|
||||
public String getDiskType()
|
||||
{
|
||||
return NetDiskConstants.DISK_QUARK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NetDiskCheckResult check(String linkUrl)
|
||||
{
|
||||
long startedAt = System.currentTimeMillis();
|
||||
String url = StringUtils.trim(linkUrl);
|
||||
String shareId = parseShareId(url);
|
||||
if (shareId == null)
|
||||
{
|
||||
return result(linkUrl, NetDiskConstants.STATUS_FORMAT_ERROR, "FORMAT",
|
||||
"夸克网盘链接格式不正确", startedAt);
|
||||
}
|
||||
|
||||
String passcode = getQueryParameter(url, "pwd");
|
||||
if (StringUtils.isBlank(passcode))
|
||||
{
|
||||
passcode = getQueryParameter(url, "passcode");
|
||||
}
|
||||
|
||||
JSONObject payload = new JSONObject();
|
||||
payload.put("pwd_id", shareId);
|
||||
payload.put("passcode", StringUtils.defaultString(passcode));
|
||||
payload.put("support_visit_limit_private_share", true);
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.url(TOKEN_API)
|
||||
.header("User-Agent", USER_AGENT)
|
||||
.header("Origin", "https://pan.quark.cn")
|
||||
.header("Referer", "https://pan.quark.cn/")
|
||||
.post(RequestBody.create(JSON_MEDIA_TYPE, payload.toJSONString()))
|
||||
.build();
|
||||
|
||||
try (Response response = httpClient.newCall(request).execute())
|
||||
{
|
||||
String body = readBody(response.body());
|
||||
JSONObject json = parseJson(body);
|
||||
int providerCode = json == null || !json.containsKey("code")
|
||||
? Integer.MIN_VALUE : json.getIntValue("code");
|
||||
String message = json == null ? null : json.getString("message");
|
||||
|
||||
if (providerCode == 0 && response.isSuccessful())
|
||||
{
|
||||
return result(linkUrl, NetDiskConstants.STATUS_VALID, "0",
|
||||
"分享链接有效", startedAt);
|
||||
}
|
||||
if (providerCode == 41008)
|
||||
{
|
||||
return result(linkUrl, NetDiskConstants.STATUS_NEED_CODE,
|
||||
String.valueOf(providerCode), "分享存在,但链接中没有提取码", startedAt);
|
||||
}
|
||||
if (providerCode == 41007 || providerCode == 41021)
|
||||
{
|
||||
return result(linkUrl, NetDiskConstants.STATUS_CODE_ERROR,
|
||||
String.valueOf(providerCode), "分享存在,但提取码错误", startedAt);
|
||||
}
|
||||
if (INVALID_CODES.contains(providerCode))
|
||||
{
|
||||
return result(linkUrl, NetDiskConstants.STATUS_INVALID,
|
||||
String.valueOf(providerCode),
|
||||
StringUtils.defaultIfBlank(message, "分享已失效、取消或不存在"), startedAt);
|
||||
}
|
||||
if (providerCode == 41022 || providerCode == 41023)
|
||||
{
|
||||
return result(linkUrl, NetDiskConstants.STATUS_UNKNOWN,
|
||||
String.valueOf(providerCode), "分享内容正在审核,暂时无法确认", startedAt);
|
||||
}
|
||||
if (providerCode == 45058 || response.code() == 403 || response.code() == 429
|
||||
|| response.code() >= 500)
|
||||
{
|
||||
return result(linkUrl, NetDiskConstants.STATUS_UNKNOWN,
|
||||
providerCode == Integer.MIN_VALUE
|
||||
? String.valueOf(response.code()) : String.valueOf(providerCode),
|
||||
"夸克网盘暂时拒绝检测或访问受限", startedAt);
|
||||
}
|
||||
return result(linkUrl, NetDiskConstants.STATUS_UNKNOWN,
|
||||
providerCode == Integer.MIN_VALUE
|
||||
? String.valueOf(response.code()) : String.valueOf(providerCode),
|
||||
StringUtils.defaultIfBlank(message, "夸克网盘返回了未识别的状态"), startedAt);
|
||||
}
|
||||
catch (IOException | RuntimeException e)
|
||||
{
|
||||
return result(linkUrl, NetDiskConstants.STATUS_UNKNOWN, "NETWORK",
|
||||
"检测请求失败:" + safeMessage(e), startedAt);
|
||||
}
|
||||
}
|
||||
|
||||
private NetDiskCheckResult result(String linkUrl, String status, String providerCode,
|
||||
String message, long startedAt)
|
||||
{
|
||||
return new NetDiskCheckResult(getDiskType(), linkUrl, status, providerCode, message,
|
||||
System.currentTimeMillis() - startedAt);
|
||||
}
|
||||
|
||||
private String parseShareId(String url)
|
||||
{
|
||||
try
|
||||
{
|
||||
URI uri = new URI(url);
|
||||
if (!"https".equalsIgnoreCase(uri.getScheme())
|
||||
|| uri.getUserInfo() != null
|
||||
|| (uri.getPort() != -1 && uri.getPort() != 443)
|
||||
|| uri.getHost() == null
|
||||
|| !"pan.quark.cn".equalsIgnoreCase(uri.getHost()))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
String[] pathParts = StringUtils.defaultString(uri.getPath()).split("/");
|
||||
if (pathParts.length < 3 || !"s".equals(pathParts[1])
|
||||
|| !pathParts[2].matches("[A-Za-z0-9_-]{6,64}"))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return pathParts[2];
|
||||
}
|
||||
catch (URISyntaxException e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String getQueryParameter(String url, String name)
|
||||
{
|
||||
okhttp3.HttpUrl httpUrl = okhttp3.HttpUrl.parse(url);
|
||||
return httpUrl == null ? null : httpUrl.queryParameter(name);
|
||||
}
|
||||
|
||||
private JSONObject parseJson(String body)
|
||||
{
|
||||
try
|
||||
{
|
||||
return StringUtils.isBlank(body) ? null : JSON.parseObject(body);
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String readBody(ResponseBody responseBody) throws IOException
|
||||
{
|
||||
return responseBody == null ? "" : responseBody.string();
|
||||
}
|
||||
|
||||
private String safeMessage(Exception e)
|
||||
{
|
||||
return StringUtils.defaultIfBlank(e.getMessage(), e.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="pictureFile != null and pictureFile != ''"> and picture_file = #{pictureFile}</if>
|
||||
<if test="videoFile != null and videoFile != ''"> and video_file = #{videoFile}</if>
|
||||
</where>
|
||||
ORDER BY code_name DESC
|
||||
ORDER BY code_id DESC
|
||||
</select>
|
||||
|
||||
<select id="selectTtCodeByCodeId" parameterType="Long" resultMap="TtCodeResult">
|
||||
@@ -106,4 +106,4 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
#{codeId}
|
||||
</foreach>
|
||||
</delete>
|
||||
</mapper>
|
||||
</mapper>
|
||||
|
||||
@@ -16,12 +16,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</sql>
|
||||
|
||||
<select id="selectTtFileList" parameterType="TtFile" resultMap="TtFileResult">
|
||||
<include refid="selectTtFileVo"/>
|
||||
select f.file_id, f.file_name, f.file_url, f.code_name
|
||||
from tt_file f
|
||||
left join (
|
||||
select code_name, max(code_id) as source_order
|
||||
from tt_code
|
||||
group by code_name
|
||||
) c on c.code_name = f.code_name
|
||||
<where>
|
||||
<if test="fileName != null and fileName != ''"> and file_name like concat('%', #{fileName}, '%')</if>
|
||||
<if test="codeName != null and codeName != ''"> and code_name like concat('%', #{codeName}, '%')</if>
|
||||
<if test="fileName != null and fileName != ''"> and f.file_name like concat('%', #{fileName}, '%')</if>
|
||||
<if test="codeName != null and codeName != ''"> and f.code_name like concat('%', #{codeName}, '%')</if>
|
||||
</where>
|
||||
ORDER BY code_name DESC, file_id ASC
|
||||
ORDER BY c.source_order DESC, f.file_id ASC
|
||||
</select>
|
||||
|
||||
<select id="selectTtFileByFileId" parameterType="Long" resultMap="TtFileResult">
|
||||
@@ -68,4 +74,4 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
#{fileId}
|
||||
</foreach>
|
||||
</delete>
|
||||
</mapper>
|
||||
</mapper>
|
||||
|
||||
@@ -14,34 +14,64 @@
|
||||
<result property="projectUrl" column="project_url" />
|
||||
<result property="projectVurl" column="project_vurl" />
|
||||
<result property="projectBaiduUrl" column="project_baidu_url" />
|
||||
<result property="quarkCheckStatus" column="quark_check_status" />
|
||||
<result property="quarkCheckMessage" column="quark_check_message" />
|
||||
<result property="quarkCheckedAt" column="quark_checked_at" />
|
||||
<result property="baiduCheckStatus" column="baidu_check_status" />
|
||||
<result property="baiduCheckMessage" column="baidu_check_message" />
|
||||
<result property="baiduCheckedAt" column="baidu_checked_at" />
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectTtProjectInfoVo">
|
||||
select id, project_num, project_num1, project_name, project_name1, project_desc, project_url, project_vurl, project_baidu_url from tt_project_info
|
||||
select p.id,
|
||||
p.project_num,
|
||||
p.project_num1,
|
||||
p.project_name,
|
||||
p.project_name1,
|
||||
p.project_desc,
|
||||
p.project_url,
|
||||
p.project_vurl,
|
||||
p.project_baidu_url,
|
||||
quark_check.check_status as quark_check_status,
|
||||
quark_check.check_message as quark_check_message,
|
||||
quark_check.checked_at as quark_checked_at,
|
||||
baidu_check.check_status as baidu_check_status,
|
||||
baidu_check.check_message as baidu_check_message,
|
||||
baidu_check.checked_at as baidu_checked_at
|
||||
from tt_project_info p
|
||||
left join tt_project_link_check quark_check
|
||||
on quark_check.project_id = p.id
|
||||
and quark_check.disk_type = 'QUARK'
|
||||
and quark_check.link_url = p.project_url
|
||||
left join tt_project_link_check baidu_check
|
||||
on baidu_check.project_id = p.id
|
||||
and baidu_check.disk_type = 'BAIDU'
|
||||
and baidu_check.link_url = p.project_baidu_url
|
||||
</sql>
|
||||
|
||||
<select id="selectTtProjectInfoList" parameterType="TtProjectInfo" resultMap="TtProjectInfoResult">
|
||||
<include refid="selectTtProjectInfoVo"/>
|
||||
<where>
|
||||
<if test="projectNum != null and projectNum != ''"> and project_num like concat('%', #{projectNum}, '%')</if>
|
||||
<if test="projectNum1 != null and projectNum1 != ''"> and project_num1 = #{projectNum1}</if>
|
||||
<if test="projectName != null and projectName != ''"> and project_name like concat('%', #{projectName}, '%')</if>
|
||||
<if test="projectName1 != null and projectName1 != ''"> and project_name1 like concat('%', #{projectName1}, '%')</if>
|
||||
<if test="projectDesc != null and projectDesc != ''"> and project_desc = #{projectDesc}</if>
|
||||
<if test="projectUrl != null and projectUrl != ''"> and project_url = #{projectUrl}</if>
|
||||
<if test="projectVurl != null and projectVurl != ''"> and project_vurl = #{projectVurl}</if>
|
||||
<if test="projectBaiduUrl != null and projectBaiduUrl != ''"> and project_baidu_url = #{projectBaiduUrl}</if>
|
||||
<if test="projectNum != null and projectNum != ''"> and p.project_num like concat('%', #{projectNum}, '%')</if>
|
||||
<if test="projectNum1 != null and projectNum1 != ''"> and p.project_num1 = #{projectNum1}</if>
|
||||
<if test="projectName != null and projectName != ''"> and p.project_name like concat('%', #{projectName}, '%')</if>
|
||||
<if test="projectName1 != null and projectName1 != ''"> and p.project_name1 like concat('%', #{projectName1}, '%')</if>
|
||||
<if test="projectDesc != null and projectDesc != ''"> and p.project_desc = #{projectDesc}</if>
|
||||
<if test="projectUrl != null and projectUrl != ''"> and p.project_url = #{projectUrl}</if>
|
||||
<if test="projectVurl != null and projectVurl != ''"> and p.project_vurl = #{projectVurl}</if>
|
||||
<if test="projectBaiduUrl != null and projectBaiduUrl != ''"> and p.project_baidu_url = #{projectBaiduUrl}</if>
|
||||
</where>
|
||||
ORDER BY p.id DESC
|
||||
</select>
|
||||
|
||||
<select id="selectTtProjectInfoById" parameterType="Integer" resultMap="TtProjectInfoResult">
|
||||
<include refid="selectTtProjectInfoVo"/>
|
||||
where id = #{id}
|
||||
where p.id = #{id}
|
||||
</select>
|
||||
|
||||
<select id="selectTtProjectInfoByName" parameterType="String" resultMap="TtProjectInfoResult">
|
||||
<include refid="selectTtProjectInfoVo"/>
|
||||
where project_name1 = #{codeName}
|
||||
where p.project_name1 = #{codeName}
|
||||
</select>
|
||||
|
||||
<insert id="insertTtProjectInfo" parameterType="TtProjectInfo" useGeneratedKeys="true" keyProperty="id">
|
||||
@@ -96,8 +126,8 @@
|
||||
|
||||
<select id="lastUpdateList" resultMap="TtProjectInfoResult" parameterType="string">
|
||||
<include refid="selectTtProjectInfoVo"/>
|
||||
where project_vurl is not null
|
||||
<if test="searchKey != null and searchKey != ''">AND IFNULL(project_name1, project_name) like CONCAT('%',#{searchKey},'%') </if>
|
||||
ORDER BY project_name DESC
|
||||
where p.project_vurl is not null
|
||||
<if test="searchKey != null and searchKey != ''">AND IFNULL(p.project_name1, p.project_name) like CONCAT('%',#{searchKey},'%') </if>
|
||||
ORDER BY p.project_name DESC
|
||||
</select>
|
||||
</mapper>
|
||||
</mapper>
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
<?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="com.ruoyi.office.mapper.TtProjectLinkCheckMapper">
|
||||
|
||||
<insert id="upsertTtProjectLinkCheck" parameterType="TtProjectLinkCheck" useGeneratedKeys="true" keyProperty="id">
|
||||
insert into tt_project_link_check
|
||||
(
|
||||
project_id,
|
||||
disk_type,
|
||||
link_url,
|
||||
check_status,
|
||||
provider_code,
|
||||
check_message,
|
||||
response_time_ms,
|
||||
checked_at,
|
||||
create_time,
|
||||
update_time
|
||||
)
|
||||
values
|
||||
(
|
||||
#{projectId},
|
||||
#{diskType},
|
||||
#{linkUrl},
|
||||
#{checkStatus},
|
||||
#{providerCode},
|
||||
#{checkMessage},
|
||||
#{responseTimeMs},
|
||||
#{checkedAt},
|
||||
now(),
|
||||
now()
|
||||
)
|
||||
on duplicate key update
|
||||
link_url = values(link_url),
|
||||
check_status = values(check_status),
|
||||
provider_code = values(provider_code),
|
||||
check_message = values(check_message),
|
||||
response_time_ms = values(response_time_ms),
|
||||
checked_at = values(checked_at),
|
||||
update_time = now()
|
||||
</insert>
|
||||
|
||||
<delete id="deleteByProjectId" parameterType="Integer">
|
||||
delete from tt_project_link_check where project_id = #{projectId}
|
||||
</delete>
|
||||
|
||||
<delete id="deleteByProjectIds">
|
||||
delete from tt_project_link_check
|
||||
where project_id in
|
||||
<foreach item="projectId" collection="array" open="(" separator="," close=")">
|
||||
#{projectId}
|
||||
</foreach>
|
||||
</delete>
|
||||
</mapper>
|
||||
Reference in New Issue
Block a user