获取minioi文件下载的预签名url

This commit is contained in:
2026-01-20 09:27:11 +08:00
parent bbf0976e12
commit dad9af3814
57 changed files with 594 additions and 1 deletions

View File

@@ -14,6 +14,7 @@ import com.sdm.common.log.annotation.SysLog;
import com.sdm.data.model.entity.FileMetadataInfo;
import com.sdm.data.model.req.*;
import com.sdm.data.model.resp.KKFileViewURLFromMinioResp;
import com.sdm.data.model.resp.MinioDownloadUrlResp;
import com.sdm.data.service.IDataFileService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@@ -411,6 +412,12 @@ public class DataFileController implements IDataFeignClient {
return IDataFileService.getKKFileViewURLFromMinio(fileId);
}
@GetMapping("/getMinioPresignedUrl")
@Operation(summary = "获取MinIO文件下载的预签名URL", description = "获取MinIO文件的预签名URL")
public SdmResponse<MinioDownloadUrlResp> getMinioPresignedUrl(@Parameter(description = "文件id") @RequestParam("fileId") Long fileId) {
return IDataFileService.getMinioDownloadUrl(fileId);
}
@GetMapping("/queryFileMetadataInfo")
@Operation(summary = "根据节点uuid获取节点文件夹信息", description = "获取节点文件夹信息")
public SdmResponse<FileMetadataInfoResp> queryFileMetadataInfo(@RequestParam(value = "uuid") String uuid, @RequestParam(value = "uuidOwnType") String uuidOwnType, @RequestParam(value = "dirId") Long dirId) {

View File

@@ -0,0 +1,23 @@
package com.sdm.data.model.resp;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* Minio下载URL响应类
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class MinioDownloadUrlResp {
/**
* minioDownloadUrl : minio的带签名下载URL
*/
private String minioDownloadUrl;
/**
* fileName : 文件名
*/
private String fileName;
}

View File

@@ -9,6 +9,7 @@ import com.sdm.common.entity.resp.data.ChunkUploadMinioFileResp;
import com.sdm.common.entity.resp.data.FileMetadataInfoResp;
import com.sdm.data.model.req.*;
import com.sdm.data.model.resp.KKFileViewURLFromMinioResp;
import com.sdm.data.model.resp.MinioDownloadUrlResp;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
@@ -240,6 +241,15 @@ public interface IDataFileService {
return null;
}
/**
* 获取Minio带签名的下载URL用于直接下载文件
* @param fileId 文件id
* @return 带签名的下载URL响应
*/
default SdmResponse<MinioDownloadUrlResp> getMinioDownloadUrl(Long fileId){
return null;
}

View File

@@ -106,8 +106,23 @@ public interface IMinioService {
*/
List<String> queryFilesByTags(Map<String, String> tags, String bucketName) throws Exception;
/**
* 获取MinIO文件预览的预签名URL
* @param objectKey 文件名objectKey
* @param bucketName 桶名称
* @return 预签名URL
*/
String getMinioPresignedUrl(String objectKey, String bucketName);
/**
* 获取MinIO文件下载的预签名URL
* @param objectKey 文件名objectKey
* @param bucketName 桶名称
* @param fileName 文件名
* @return
*/
String getMinioDownloadPresignedUrl(String objectKey, String bucketName, String fileName);
Boolean chunkUpload(String bucketName, MultipartFile file, String fileName,Map<String, String> tags);
Boolean merge(String tempBucketName,String tempFilePath,String mergeBucketName,String fileName);

View File

@@ -44,6 +44,7 @@ import com.sdm.common.entity.resp.data.PoolInfo;
import com.sdm.data.model.enums.ApproveFileActionENUM;
import com.sdm.data.model.req.*;
import com.sdm.data.model.resp.KKFileViewURLFromMinioResp;
import com.sdm.data.model.resp.MinioDownloadUrlResp;
import com.sdm.data.service.*;
import com.sdm.data.service.approve.FileApproveExecutor;
import com.sdm.data.service.approve.FileApproveRequestBuilder;
@@ -2217,6 +2218,23 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
return SdmResponse.success(kkFileViewURLFromMinioResp);
}
@Override
public SdmResponse<MinioDownloadUrlResp> getMinioDownloadUrl(Long fileId) {
FileMetadataInfo fileMetadataInfo = fileMetadataInfoService.getById(fileId);
if (fileMetadataInfo == null) {
return SdmResponse.failed("文件不存在");
}
String objectKey = fileMetadataInfo.getObjectKey();
String fileName = fileMetadataInfo.getOriginalName();
String minioDownloadUrl = minioService.getMinioDownloadPresignedUrl(objectKey, fileMetadataInfo.getBucketName(), fileName);
if (minioDownloadUrl == null) {
return SdmResponse.failed("获取下载链接失败");
}
MinioDownloadUrlResp resp = new MinioDownloadUrlResp(minioDownloadUrl, fileName);
return SdmResponse.success(resp);
}
/**
* 构建带时间戳的 KKFileView URL
*

View File

@@ -630,7 +630,13 @@ public class MinioService implements IMinioService {
}
}
/**
* 获取MinIO文件预览的预签名URL
* @param objectKey 文件名objectKey
* @param bucketName 桶名称
* @return
*/
public String getMinioPresignedUrl(String objectKey, String bucketName) {
String presignedUrl = null;
try {
@@ -644,6 +650,39 @@ public class MinioService implements IMinioService {
return presignedUrl;
}
/**
* 生成带签名的下载URL强制下载非预览
*
* @param objectKey 对象键
* @param bucketName 桶名称
* @param fileName 下载时显示的文件名
* @return 预签名下载URL
*/
public String getMinioDownloadPresignedUrl(String objectKey, String bucketName, String fileName) {
String presignedUrl = null;
try {
// 对文件名进行URL编码防止中文和特殊字符问题
String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
// 设置响应头,强制下载
Map<String, String> reqParams = new HashMap<>();
reqParams.put("response-content-disposition", "attachment; filename=\"" + encodedFileName + "\"; filename*=utf-8''" + encodedFileName);
// 生成预签名URL
GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(getBucketName(bucketName))
.object(objectKey)
.expiry(3600, TimeUnit.SECONDS)
.extraQueryParams(reqParams)
.build();
presignedUrl = minioClient.getPresignedObjectUrl(args);
} catch (Exception e) {
log.error("获取文件下载URL失败: " + objectKey, e);
return null;
}
return presignedUrl;
}
/**
* description: 分片碎文件上传
*

View File

@@ -0,0 +1,333 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MinIO文件下载测试</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.container {
background: white;
padding: 40px;
border-radius: 16px;
box-shadow: 0 10px 40px rgba(0,0,0,0.2);
width: 450px;
}
h1 {
text-align: center;
color: #333;
margin-bottom: 30px;
font-size: 24px;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 8px;
color: #555;
font-weight: 500;
}
input[type="text"] {
width: 100%;
padding: 12px 16px;
border: 2px solid #e0e0e0;
border-radius: 8px;
font-size: 16px;
transition: border-color 0.3s;
}
input[type="text"]:focus {
outline: none;
border-color: #667eea;
}
.btn {
width: 100%;
padding: 14px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
border-radius: 8px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s;
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 5px 20px rgba(102, 126, 234, 0.4);
}
.btn:active {
transform: translateY(0);
}
.result {
margin-top: 20px;
padding: 15px;
background: #f8f9fa;
border-radius: 8px;
display: none;
}
.result.show {
display: block;
}
.result.success {
background: #d4edda;
border: 1px solid #c3e6cb;
}
.result.error {
background: #f8d7da;
border: 1px solid #f5c6cb;
}
.result-title {
font-weight: 600;
margin-bottom: 8px;
}
.result-content {
word-break: break-all;
font-size: 14px;
color: #666;
}
.download-link {
display: inline-block;
margin-top: 10px;
color: #667eea;
text-decoration: underline;
cursor: pointer;
}
.log-section {
margin-top: 20px;
border: 1px solid #e0e0e0;
border-radius: 8px;
overflow: hidden;
}
.log-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 15px;
background: #f5f5f5;
border-bottom: 1px solid #e0e0e0;
font-weight: 600;
color: #555;
}
.clear-btn {
padding: 4px 12px;
background: #ff6b6b;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 12px;
}
.clear-btn:hover {
background: #ee5a5a;
}
.log-container {
max-height: 200px;
overflow-y: auto;
padding: 10px;
background: #1e1e1e;
font-family: 'Consolas', 'Monaco', monospace;
font-size: 12px;
}
.log-item {
padding: 4px 0;
border-bottom: 1px solid #333;
word-break: break-all;
}
.log-item:last-child {
border-bottom: none;
}
.log-time {
color: #888;
margin-right: 8px;
}
.log-info { color: #4fc3f7; }
.log-success { color: #81c784; }
.log-error { color: #ef5350; }
.log-data { color: #ffb74d; }
.loading {
display: none;
text-align: center;
margin-top: 15px;
}
.loading.show {
display: block;
}
.spinner {
border: 3px solid #f3f3f3;
border-top: 3px solid #667eea;
border-radius: 50%;
width: 30px;
height: 30px;
animation: spin 1s linear infinite;
margin: 0 auto;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
</head>
<body>
<div class="container">
<h1>MinIO 文件下载测试</h1>
<div class="form-group">
<label for="fileId">文件 ID</label>
<input type="text" id="fileId" placeholder="请输入文件ID例如: 123456">
</div>
<button class="btn" onclick="downloadFile()">获取下载链接并下载</button>
<div class="loading" id="loading">
<div class="spinner"></div>
<p style="margin-top: 10px; color: #666;">正在获取下载链接...</p>
</div>
<div class="result" id="result">
<div class="result-title" id="resultTitle"></div>
<div class="result-content" id="resultContent"></div>
<span class="download-link" id="downloadLink" onclick="openDownloadUrl()" style="display:none;">点击此处重新下载</span>
</div>
<div class="log-section">
<div class="log-header">
<span>请求日志</span>
<button class="clear-btn" onclick="clearLog()">清空</button>
</div>
<div class="log-container" id="logContainer"></div>
</div>
</div>
<script>
// 保存下载URL用于重复下载
let currentDownloadUrl = '';
// 添加日志
function addLog(message, type = 'info') {
const logContainer = document.getElementById('logContainer');
const logItem = document.createElement('div');
logItem.className = 'log-item';
const now = new Date();
const timeStr = now.toLocaleTimeString('zh-CN', { hour12: false }) + '.' + String(now.getMilliseconds()).padStart(3, '0');
logItem.innerHTML = `<span class="log-time">[${timeStr}]</span><span class="log-${type}">${message}</span>`;
logContainer.appendChild(logItem);
logContainer.scrollTop = logContainer.scrollHeight;
}
// 清空日志
function clearLog() {
document.getElementById('logContainer').innerHTML = '';
}
async function downloadFile() {
const fileId = document.getElementById('fileId').value.trim();
if (!fileId) {
showResult('error', '错误', '请输入文件ID');
addLog('错误: 请输入文件ID', 'error');
return;
}
// 显示加载状态
showLoading(true);
hideResult();
const requestUrl = `http://192.168.65.161:7100/simulation/data/data/getMinioPresignedUrl?fileId=${fileId}`;
addLog(`发起请求: ${requestUrl}`, 'info');
try {
// 调用接口获取下载链接
const response = await fetch(requestUrl, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
});
addLog(`响应状态: ${response.status} ${response.statusText}`, response.ok ? 'success' : 'error');
const data = await response.json();
addLog(`响应数据: ${JSON.stringify(data)}`, 'data');
if (data.code === 200 && data.data) {
const downloadUrl = data.data.minioDownloadUrl;
const fileName = data.data.fileName;
currentDownloadUrl = downloadUrl;
addLog(`获取成功 - 文件名: ${fileName}`, 'success');
addLog(`下载链接: ${downloadUrl}`, 'success');
// 显示成功信息
showResult('success', '获取成功', `文件名: ${fileName}`);
document.getElementById('downloadLink').style.display = 'inline-block';
// 使用 window.open 打开新页面下载
addLog('正在打开新窗口下载...', 'info');
window.open(downloadUrl, '_blank');
} else {
const errorMsg = data.msg || '未知错误';
addLog(`获取失败: ${errorMsg}`, 'error');
showResult('error', '获取失败', errorMsg);
}
} catch (error) {
console.error('请求失败:', error);
addLog(`请求异常: ${error.message || '网络错误'}`, 'error');
showResult('error', '请求失败', error.message || '网络错误,请检查服务是否启动');
} finally {
showLoading(false);
}
}
function openDownloadUrl() {
if (currentDownloadUrl) {
window.open(currentDownloadUrl, '_blank');
}
}
function showLoading(show) {
document.getElementById('loading').className = show ? 'loading show' : 'loading';
}
function showResult(type, title, content) {
const resultDiv = document.getElementById('result');
const resultTitle = document.getElementById('resultTitle');
const resultContent = document.getElementById('resultContent');
resultDiv.className = `result show ${type}`;
resultTitle.textContent = title;
resultContent.textContent = content;
}
function hideResult() {
document.getElementById('result').className = 'result';
document.getElementById('downloadLink').style.display = 'none';
}
// 支持回车键触发下载
document.getElementById('fileId').addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
downloadFile();
}
});
</script>
</body>
</html>

View File

@@ -0,0 +1,12 @@
{
"groups": [
{
"name": "spring.datasource.second",
"type": "javax.sql.DataSource",
"sourceType": "com.sdm.outbridge.config.SecondMybatisPlusConfig",
"sourceMethod": "secondDataSource()"
}
],
"properties": [],
"hints": []
}

View File

@@ -0,0 +1,45 @@
spring:
datasource:
second:
username: EP_DM
password: EP_DM@123.COM
# username: root
# password: mysql
# todo 生产地址
jdbc-url: jdbc:mysql://10.122.48.11:13306/easy_project?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Asia/Shanghai
# jdbc-url: jdbc:mysql://127.0.0.1:3306/second_db?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
# 测试开发环境
#appKey : 380ad3deb578424c9ca5178383f732c1
#appSecret : 805c316f35024b8b9566ca67b4991c42
#appKey : d39820947556421aa329b070e669dfa2
#corpKey : e906d13947944947921bb32c8fcffc6e
#appSecret : 13cff5f8fb1c479297370a7d41853158
appKey : e9eb516aa02a43a29e227a0d901ec5f1
appSecret : 9fac43db08634aaf8a9fe5fb9468de9d
# 海葵云url
HK_CLOUD_URL : https://v15.lyh.haikuicloud.com
# 1. 海葵云获取用户token url后缀
HK_USER_TOKEN_URL_SUFFIX: /merchant/openapi/user/login/jobNo
# 2. 海葵云获取单个用户信息url后缀
HK_SIMPLE_USER_URL_SUFFIX: /merchant/api/user/getSimpleUserInfo
# 3. 海葵云上传文件url后缀
HK_UPLOAD_FILE_URL_SUFFIX: /haikui-oa/autoCreateFlow/uploadFile
# 获取项目工位实例号
HK_GET_PROCESS_DATA_SUFFIX: /haikui-oa/autoCreateFlow/getProcessData/oa_three_d_review
# EP系统URL
#EP_URL : https://ep-url.dev.haikuicloud.com
# 开发环境
EP_URL: https://ep-url-test.lyh.haikuicloud.com
# 推送代办状态url后缀
QUERY_TODO_STATUS_SUFFIX: /todoApi/todo/emulation/dm/status
# 查询待办结果url后缀
QUERY_TODO_RESULT_SUFFIX: /todoApi/todo/emulation/dm/result
# 6. 查询待办附加url后缀
QUERY_TOD_ATTACHMENT_SUFFIX: /todoApi/todo/emulation/dm/attachments
# 即时通url
FREELINK_URL: http://freelink.haikui.com
FREELINK_PUSH_MSG_SUFFIX: /webchat/InformApi/FreelinkAndDingdingInform

View File

@@ -0,0 +1,3 @@
artifactId=outbridge
groupId=com.sdm
version=0.0.1-SNAPSHOT

View File

@@ -0,0 +1,45 @@
com\sdm\outbridge\entity\LyricVProjectToDM.class
com\sdm\outbridge\service\lyric\LyricVProjectBatchToDmService.class
com\sdm\outbridge\service\impl\lyric\LyricVProjectBatchToDMServiceImpl.class
com\sdm\outbridge\dao\LyricVProjectToDmMapper.class
com\sdm\outbridge\service\impl\lyric\LyricVProjectToDmServiceImpl.class
com\sdm\outbridge\service\impl\lyric\FreeLinkServiceImpl.class
com\sdm\outbridge\config\CommonConfig.class
com\sdm\outbridge\config\CommonConfig$YamlPropertySourceFactory.class
META-INF\spring-configuration-metadata.json
com\sdm\outbridge\service\impl\lyric\LyricVMainPlanDMServiceImpl.class
com\sdm\outbridge\service\impl\lyric\LyricVProductionLineToDmServiceImpl.class
com\sdm\outbridge\dao\LyricVPdtDmMapper.class
com\sdm\outbridge\mode\FreeLinkParamDto.class
com\sdm\outbridge\mode\LyricAttachmentInfo.class
com\sdm\outbridge\mode\GetProcessDataReq.class
com\sdm\outbridge\mode\FreeLinkResp.class
com\sdm\outbridge\mode\LyricProjectBaseInfo.class
com\sdm\outbridge\service\impl\lyric\LyricVTodoInfoServiceImpl.class
com\sdm\outbridge\mode\GetProcessDataCondition.class
com\sdm\outbridge\mode\LyricMainPlanInfo.class
com\sdm\outbridge\mode\LyricProjectBatchInfo.class
com\sdm\outbridge\mode\LyricProjectPdt.class
com\sdm\outbridge\service\impl\lyric\LyricVPdtDmServiceImpl.class
com\sdm\outbridge\mode\FreeLinkMsg.class
com\sdm\outbridge\service\lyric\LyricVProjectToDmService.class
com\sdm\outbridge\service\lyric\LyricIntegrateService.class
com\sdm\outbridge\service\lyric\LyricVProductionLineToDmService.class
com\sdm\outbridge\dao\LyricVTodoInfoMapper.class
com\sdm\outbridge\mode\HkCloudSignObject.class
com\sdm\outbridge\mode\LyricTodoEntity.class
com\sdm\outbridge\entity\LyricVProjectBatchToDM.class
com\sdm\outbridge\mode\HkUploadFileReq.class
com\sdm\outbridge\config\SecondMybatisPlusConfig.class
com\sdm\outbridge\service\lyric\LyricVMainPlanDMService.class
com\sdm\outbridge\entity\LyricVMainPlanDM.class
com\sdm\outbridge\mode\FreelinkAndDingdingInformReq.class
com\sdm\outbridge\dao\LyricVMainPlanDMMapper.class
com\sdm\outbridge\service\lyric\LyricVPdtDmService.class
com\sdm\outbridge\dao\LyricVProductionLineToDmMapper.class
com\sdm\outbridge\entity\LyricVProductionLineToDM.class
com\sdm\outbridge\service\lyric\IFreeLinkService.class
com\sdm\outbridge\service\lyric\LyricVTodoInfoService.class
com\sdm\outbridge\dao\LyricVProjectBatchToDMMapper.class
com\sdm\outbridge\entity\LyricVPdtToDM.class
com\sdm\outbridge\entity\LyricVTodoEmulationInfoDM.class

View File

@@ -0,0 +1,43 @@
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\service\lyric\LyricVProjectToDmService.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\service\lyric\LyricIntegrateService.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\config\SecondMybatisPlusConfig.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\service\lyric\LyricVTodoInfoService.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\entity\LyricVProductionLineToDM.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\mode\GetProcessDataCondition.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\mode\GetProcessDataReq.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\mode\LyricAttachmentInfo.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\mode\HkCloudSignObject.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\service\impl\lyric\LyricVProjectToDmServiceImpl.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\service\impl\lyric\LyricVPdtDmServiceImpl.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\mode\FreeLinkResp.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\entity\LyricVProjectBatchToDM.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\dao\LyricVProjectBatchToDMMapper.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\entity\LyricVMainPlanDM.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\entity\LyricVTodoEmulationInfoDM.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\service\impl\lyric\FreeLinkServiceImpl.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\dao\LyricVPdtDmMapper.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\service\lyric\LyricVProjectBatchToDmService.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\service\lyric\LyricVProductionLineToDmService.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\dao\LyricVTodoInfoMapper.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\mode\HkUploadFileReq.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\mode\LyricMainPlanInfo.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\service\impl\lyric\LyricVProductionLineToDmServiceImpl.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\dao\LyricVProductionLineToDmMapper.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\mode\LyricProjectPdt.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\dao\LyricVMainPlanDMMapper.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\entity\LyricVPdtToDM.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\mode\LyricProjectBaseInfo.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\service\lyric\LyricVMainPlanDMService.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\mode\LyricProjectBatchInfo.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\service\impl\lyric\LyricVTodoInfoServiceImpl.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\service\lyric\LyricVPdtDmService.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\config\CommonConfig.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\mode\FreelinkAndDingdingInformReq.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\entity\LyricVProjectToDM.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\service\impl\lyric\LyricVMainPlanDMServiceImpl.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\mode\FreeLinkParamDto.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\service\impl\lyric\LyricVProjectBatchToDMServiceImpl.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\mode\LyricTodoEntity.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\service\lyric\IFreeLinkService.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\dao\LyricVProjectToDmMapper.java
D:\idea-Project\spdm-backend\outbridge\src\main\java\com\sdm\outbridge\mode\FreeLinkMsg.java

Binary file not shown.