792 lines
25 KiB
Markdown
792 lines
25 KiB
Markdown
# Prompt - 元数据组件索引和查询
|
||
|
||
## 输入引用
|
||
|
||
引用相关的 docs 文档链接:
|
||
|
||
- [REQ-010-11.md](../requirements/REQ-010-11.md) - 元数据组件索引和查询需求文档
|
||
- [0020-metadata-component-index.md](../decisions/adr/0020-metadata-component-index.md) - 元数据组件索引和查询架构决策
|
||
- [REQ-010-7.md](../requirements/REQ-010-7.md) - 文件存储和解压处理需求文档
|
||
- [0016-file-storage-and-extract.md](../decisions/adr/0016-file-storage-and-extract.md) - 文件存储和解压处理架构决策
|
||
- [file/index.md](../api-docs/file/index.md) - 文件模块 API 文档索引
|
||
|
||
## Context Maps
|
||
|
||
强制列出本次 Prompt 依赖的 Canvas 文件:
|
||
|
||
- [Authentication.canvas](../Authentication.canvas) - 项目架构视觉化展示
|
||
- **相关节点**: [集成核心](node_integration_core) - 提供与Salesforce的各种连接方式
|
||
- **相关节点**: [IMetadataApiService](node_metadata_api_service) - 元数据API服务接口
|
||
- **相关节点**: [MetadataApiClient](node_metadata_api_client) - Metadata API客户端
|
||
|
||
## 目标
|
||
|
||
实现元数据组件索引和查询功能,包括组件索引创建、组件查询、组件详情查看、组件统计。支持按类型、名称、版本等条件查询元数据组件。
|
||
|
||
## 输出格式
|
||
|
||
### 代码结构
|
||
|
||
```
|
||
datai-salesforce-metadata/
|
||
├── component-index/
|
||
│ ├── controller/
|
||
│ │ └── MetadataComponentIndexController.java
|
||
│ ├── service/
|
||
│ │ ├── IMetadataComponentIndexService.java
|
||
│ │ ├── MetadataComponentIndexServiceImpl.java
|
||
│ │ ├── IMetadataComponentQueryService.java
|
||
│ │ ├── MetadataComponentQueryServiceImpl.java
|
||
│ │ ├── IMetadataComponentDetailService.java
|
||
│ │ ├── MetadataComponentDetailServiceImpl.java
|
||
│ │ ├── IMetadataComponentStatisticsService.java
|
||
│ │ └── MetadataComponentStatisticsServiceImpl.java
|
||
│ ├── entity/
|
||
│ │ └── MetadataComponentIndex.java
|
||
│ ├── mapper/
|
||
│ │ └── MetadataComponentIndexMapper.java
|
||
│ ├── dto/
|
||
│ │ ├── ComponentIndexRequest.java
|
||
│ │ ├── ComponentIndexResponse.java
|
||
│ │ ├── ComponentQueryRequest.java
|
||
│ │ ├── ComponentQueryResponse.java
|
||
│ │ ├── ComponentDetailResponse.java
|
||
│ │ ├── ComponentStatisticsResponse.java
|
||
│ │ ├── ComponentTypeDistributionResponse.java
|
||
│ │ └── ComponentVersionDistributionResponse.java
|
||
│ ├── parser/
|
||
│ │ ├── MetadataComponentParser.java
|
||
│ │ ├── ApexClassParser.java
|
||
│ │ ├── VisualforcePageParser.java
|
||
│ │ ├── CustomObjectParser.java
|
||
│ │ └── CustomFieldParser.java
|
||
│ └── exception/
|
||
│ └── ComponentIndexException.java
|
||
```
|
||
|
||
### 代码示例(语言:Java)
|
||
|
||
#### 1. MetadataComponentIndexController 控制器
|
||
|
||
```java
|
||
package com.datai.salesforce.metadata.component.controller;
|
||
|
||
import com.datai.salesforce.metadata.component.dto.*;
|
||
import com.datai.salesforce.metadata.component.service.*;
|
||
import org.springframework.beans.factory.annotation.Autowired;
|
||
import org.springframework.web.bind.annotation.*;
|
||
|
||
@RestController
|
||
@RequestMapping("/metadata/component")
|
||
public class MetadataComponentIndexController {
|
||
|
||
@Autowired
|
||
private IMetadataComponentIndexService componentIndexService;
|
||
|
||
@Autowired
|
||
private IMetadataComponentQueryService componentQueryService;
|
||
|
||
@Autowired
|
||
private IMetadataComponentDetailService componentDetailService;
|
||
|
||
@Autowired
|
||
private IMetadataComponentStatisticsService componentStatisticsService;
|
||
|
||
@PostMapping("/index")
|
||
public ComponentIndexResponse createIndex(@RequestBody ComponentIndexRequest request) {
|
||
return componentIndexService.createIndex(request);
|
||
}
|
||
|
||
@GetMapping("/query")
|
||
public ComponentQueryResponse queryComponents(
|
||
@RequestParam(required = false) String type,
|
||
@RequestParam(required = false) String name,
|
||
@RequestParam(required = false) String version,
|
||
@RequestParam(defaultValue = "1") int page,
|
||
@RequestParam(defaultValue = "10") int size) {
|
||
ComponentQueryRequest request = new ComponentQueryRequest();
|
||
request.setType(type);
|
||
request.setName(name);
|
||
request.setVersion(version);
|
||
request.setPage(page);
|
||
request.setSize(size);
|
||
return componentQueryService.queryComponents(request);
|
||
}
|
||
|
||
@GetMapping("/detail/{id}")
|
||
public ComponentDetailResponse getComponentDetail(@PathVariable Long id) {
|
||
return componentDetailService.getComponentDetail(id);
|
||
}
|
||
|
||
@GetMapping("/detail/{id}/content")
|
||
public String getComponentContent(@PathVariable Long id) {
|
||
return componentDetailService.getComponentContent(id);
|
||
}
|
||
|
||
@GetMapping("/detail/{id}/dependencies")
|
||
public ComponentDetailResponse getComponentDependencies(@PathVariable Long id) {
|
||
return componentDetailService.getComponentDependencies(id);
|
||
}
|
||
|
||
@GetMapping("/statistics")
|
||
public ComponentStatisticsResponse getStatistics(
|
||
@RequestParam(required = false) String type,
|
||
@RequestParam(required = false) String version,
|
||
@RequestParam(required = false) Long orgConfigId) {
|
||
return componentStatisticsService.getStatistics(type, version, orgConfigId);
|
||
}
|
||
|
||
@GetMapping("/statistics/type-distribution")
|
||
public ComponentTypeDistributionResponse getTypeDistribution(
|
||
@RequestParam(required = false) Long orgConfigId) {
|
||
return componentStatisticsService.getTypeDistribution(orgConfigId);
|
||
}
|
||
|
||
@GetMapping("/statistics/version-distribution")
|
||
public ComponentVersionDistributionResponse getVersionDistribution(
|
||
@RequestParam(required = false) Long orgConfigId) {
|
||
return componentStatisticsService.getVersionDistribution(orgConfigId);
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 2. IMetadataComponentIndexService 服务接口
|
||
|
||
```java
|
||
package com.datai.salesforce.metadata.component.service;
|
||
|
||
import com.datai.salesforce.metadata.component.dto.ComponentIndexRequest;
|
||
import com.datai.salesforce.metadata.component.dto.ComponentIndexResponse;
|
||
|
||
public interface IMetadataComponentIndexService {
|
||
|
||
ComponentIndexResponse createIndex(ComponentIndexRequest request);
|
||
}
|
||
```
|
||
|
||
#### 3. MetadataComponentIndexServiceImpl 服务实现
|
||
|
||
```java
|
||
package com.datai.salesforce.metadata.component.service;
|
||
|
||
import com.datai.salesforce.metadata.component.dto.ComponentIndexRequest;
|
||
import com.datai.salesforce.metadata.component.dto.ComponentIndexResponse;
|
||
import com.datai.salesforce.metadata.component.entity.MetadataComponentIndex;
|
||
import com.datai.salesforce.metadata.component.mapper.MetadataComponentIndexMapper;
|
||
import com.datai.salesforce.metadata.component.parser.MetadataComponentParser;
|
||
import com.datai.salesforce.metadata.component.parser.ApexClassParser;
|
||
import com.datai.salesforce.metadata.component.parser.VisualforcePageParser;
|
||
import com.datai.salesforce.metadata.component.parser.CustomObjectParser;
|
||
import com.datai.salesforce.metadata.component.parser.CustomFieldParser;
|
||
import com.datai.salesforce.metadata.service.IFileStorageService;
|
||
import org.springframework.beans.factory.annotation.Autowired;
|
||
import org.springframework.scheduling.annotation.Async;
|
||
import org.springframework.stereotype.Service;
|
||
import org.springframework.transaction.annotation.Transactional;
|
||
|
||
import java.io.File;
|
||
import java.util.ArrayList;
|
||
import java.util.List;
|
||
import java.util.concurrent.Future;
|
||
|
||
@Service
|
||
public class MetadataComponentIndexServiceImpl implements IMetadataComponentIndexService {
|
||
|
||
@Autowired
|
||
private MetadataComponentIndexMapper componentIndexMapper;
|
||
|
||
@Autowired
|
||
private IFileStorageService fileStorageService;
|
||
|
||
@Autowired
|
||
private ApexClassParser apexClassParser;
|
||
|
||
@Autowired
|
||
private VisualforcePageParser visualforcePageParser;
|
||
|
||
@Autowired
|
||
private CustomObjectParser customObjectParser;
|
||
|
||
@Autowired
|
||
private CustomFieldParser customFieldParser;
|
||
|
||
@Override
|
||
@Async("indexExecutor")
|
||
@Transactional
|
||
public ComponentIndexResponse createIndex(ComponentIndexRequest request) {
|
||
File extractPath = fileStorageService.getExtractPath(request.getTaskId());
|
||
|
||
List<MetadataComponentIndex> components = new ArrayList<>();
|
||
|
||
components.addAll(apexClassParser.parse(extractPath, request.getTaskId()));
|
||
components.addAll(visualforcePageParser.parse(extractPath, request.getTaskId()));
|
||
components.addAll(customObjectParser.parse(extractPath, request.getTaskId()));
|
||
components.addAll(customFieldParser.parse(extractPath, request.getTaskId()));
|
||
|
||
componentIndexMapper.insertBatch(components);
|
||
|
||
ComponentIndexResponse response = new ComponentIndexResponse();
|
||
response.setTaskId(request.getTaskId());
|
||
response.setTotal(components.size());
|
||
response.setMessage("Index created successfully");
|
||
|
||
return response;
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 4. IMetadataComponentQueryService 服务接口
|
||
|
||
```java
|
||
package com.datai.salesforce.metadata.component.service;
|
||
|
||
import com.datai.salesforce.metadata.component.dto.ComponentQueryRequest;
|
||
import com.datai.salesforce.metadata.component.dto.ComponentQueryResponse;
|
||
|
||
public interface IMetadataComponentQueryService {
|
||
|
||
ComponentQueryResponse queryComponents(ComponentQueryRequest request);
|
||
}
|
||
```
|
||
|
||
#### 5. MetadataComponentQueryServiceImpl 服务实现
|
||
|
||
```java
|
||
package com.datai.salesforce.metadata.component.service;
|
||
|
||
import com.datai.salesforce.metadata.component.dto.ComponentQueryRequest;
|
||
import com.datai.salesforce.metadata.component.dto.ComponentQueryResponse;
|
||
import com.datai.salesforce.metadata.component.entity.MetadataComponentIndex;
|
||
import com.datai.salesforce.metadata.component.mapper.MetadataComponentIndexMapper;
|
||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||
import org.springframework.beans.factory.annotation.Autowired;
|
||
import org.springframework.stereotype.Service;
|
||
|
||
@Service
|
||
public class MetadataComponentQueryServiceImpl implements IMetadataComponentQueryService {
|
||
|
||
@Autowired
|
||
private MetadataComponentIndexMapper componentIndexMapper;
|
||
|
||
@Override
|
||
public ComponentQueryResponse queryComponents(ComponentQueryRequest request) {
|
||
QueryWrapper<MetadataComponentIndex> queryWrapper = new QueryWrapper<>();
|
||
|
||
if (request.getType() != null && !request.getType().isEmpty()) {
|
||
queryWrapper.eq("component_type", request.getType());
|
||
}
|
||
|
||
if (request.getName() != null && !request.getName().isEmpty()) {
|
||
queryWrapper.like("component_name", request.getName());
|
||
}
|
||
|
||
if (request.getVersion() != null && !request.getVersion().isEmpty()) {
|
||
queryWrapper.eq("component_version", request.getVersion());
|
||
}
|
||
|
||
queryWrapper.orderByDesc("create_time");
|
||
|
||
Page<MetadataComponentIndex> pageResult = componentIndexMapper.selectPage(
|
||
new Page<>(request.getPage(), request.getSize()), queryWrapper);
|
||
|
||
ComponentQueryResponse response = new ComponentQueryResponse();
|
||
response.setTotal(pageResult.getTotal());
|
||
response.setPage(request.getPage());
|
||
response.setSize(request.getSize());
|
||
response.setRecords(pageResult.getRecords());
|
||
|
||
return response;
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 6. IMetadataComponentDetailService 服务接口
|
||
|
||
```java
|
||
package com.datai.salesforce.metadata.component.service;
|
||
|
||
import com.datai.salesforce.metadata.component.dto.ComponentDetailResponse;
|
||
|
||
public interface IMetadataComponentDetailService {
|
||
|
||
ComponentDetailResponse getComponentDetail(Long id);
|
||
|
||
String getComponentContent(Long id);
|
||
|
||
ComponentDetailResponse getComponentDependencies(Long id);
|
||
}
|
||
```
|
||
|
||
#### 7. MetadataComponentDetailServiceImpl 服务实现
|
||
|
||
```java
|
||
package com.datai.salesforce.metadata.component.service;
|
||
|
||
import com.datai.salesforce.metadata.component.dto.ComponentDetailResponse;
|
||
import com.datai.salesforce.metadata.component.entity.MetadataComponentIndex;
|
||
import com.datai.salesforce.metadata.component.mapper.MetadataComponentIndexMapper;
|
||
import com.datai.salesforce.metadata.service.IFileStorageService;
|
||
import org.springframework.beans.factory.annotation.Autowired;
|
||
import org.springframework.stereotype.Service;
|
||
|
||
import java.io.File;
|
||
import java.nio.file.Files;
|
||
import java.nio.file.Paths;
|
||
|
||
@Service
|
||
public class MetadataComponentDetailServiceImpl implements IMetadataComponentDetailService {
|
||
|
||
@Autowired
|
||
private MetadataComponentIndexMapper componentIndexMapper;
|
||
|
||
@Autowired
|
||
private IFileStorageService fileStorageService;
|
||
|
||
@Override
|
||
public ComponentDetailResponse getComponentDetail(Long id) {
|
||
MetadataComponentIndex component = componentIndexMapper.selectById(id);
|
||
if (component == null) {
|
||
throw new RuntimeException("Component not found");
|
||
}
|
||
|
||
ComponentDetailResponse response = new ComponentDetailResponse();
|
||
response.setId(component.getId());
|
||
response.setTaskId(component.getTaskId());
|
||
response.setComponentType(component.getComponentType());
|
||
response.setComponentName(component.getComponentName());
|
||
response.setComponentVersion(component.getComponentVersion());
|
||
response.setFilePath(component.getFilePath());
|
||
response.setCreateTime(component.getCreateTime());
|
||
|
||
return response;
|
||
}
|
||
|
||
@Override
|
||
public String getComponentContent(Long id) {
|
||
MetadataComponentIndex component = componentIndexMapper.selectById(id);
|
||
if (component == null) {
|
||
throw new RuntimeException("Component not found");
|
||
}
|
||
|
||
File file = new File(component.getFilePath());
|
||
try {
|
||
return new String(Files.readAllBytes(Paths.get(file.toURI())));
|
||
} catch (Exception e) {
|
||
throw new RuntimeException("Failed to read component content", e);
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public ComponentDetailResponse getComponentDependencies(Long id) {
|
||
MetadataComponentIndex component = componentIndexMapper.selectById(id);
|
||
if (component == null) {
|
||
throw new RuntimeException("Component not found");
|
||
}
|
||
|
||
ComponentDetailResponse response = new ComponentDetailResponse();
|
||
response.setId(component.getId());
|
||
response.setComponentName(component.getComponentName());
|
||
response.setComponentType(component.getComponentType());
|
||
|
||
return response;
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 8. IMetadataComponentStatisticsService 服务接口
|
||
|
||
```java
|
||
package com.datai.salesforce.metadata.component.service;
|
||
|
||
import com.datai.salesforce.metadata.component.dto.*;
|
||
|
||
public interface IMetadataComponentStatisticsService {
|
||
|
||
ComponentStatisticsResponse getStatistics(String type, String version, Long orgConfigId);
|
||
|
||
ComponentTypeDistributionResponse getTypeDistribution(Long orgConfigId);
|
||
|
||
ComponentVersionDistributionResponse getVersionDistribution(Long orgConfigId);
|
||
}
|
||
```
|
||
|
||
#### 9. MetadataComponentStatisticsServiceImpl 服务实现
|
||
|
||
```java
|
||
package com.datai.salesforce.metadata.component.service;
|
||
|
||
import com.datai.salesforce.metadata.component.dto.*;
|
||
import com.datai.salesforce.metadata.component.entity.MetadataComponentIndex;
|
||
import com.datai.salesforce.metadata.component.mapper.MetadataComponentIndexMapper;
|
||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||
import org.springframework.beans.factory.annotation.Autowired;
|
||
import org.springframework.stereotype.Service;
|
||
|
||
import java.util.List;
|
||
import java.util.Map;
|
||
import java.util.stream.Collectors;
|
||
|
||
@Service
|
||
public class MetadataComponentStatisticsServiceImpl implements IMetadataComponentStatisticsService {
|
||
|
||
@Autowired
|
||
private MetadataComponentIndexMapper componentIndexMapper;
|
||
|
||
@Override
|
||
public ComponentStatisticsResponse getStatistics(String type, String version, Long orgConfigId) {
|
||
QueryWrapper<MetadataComponentIndex> queryWrapper = new QueryWrapper<>();
|
||
|
||
if (type != null && !type.isEmpty()) {
|
||
queryWrapper.eq("component_type", type);
|
||
}
|
||
|
||
if (version != null && !version.isEmpty()) {
|
||
queryWrapper.eq("component_version", version);
|
||
}
|
||
|
||
Long total = componentIndexMapper.selectCount(queryWrapper);
|
||
|
||
ComponentStatisticsResponse response = new ComponentStatisticsResponse();
|
||
response.setTotal(total);
|
||
|
||
return response;
|
||
}
|
||
|
||
@Override
|
||
public ComponentTypeDistributionResponse getTypeDistribution(Long orgConfigId) {
|
||
QueryWrapper<MetadataComponentIndex> queryWrapper = new QueryWrapper<>();
|
||
List<MetadataComponentIndex> components = componentIndexMapper.selectList(queryWrapper);
|
||
|
||
Map<String, Long> typeDistribution = components.stream()
|
||
.collect(Collectors.groupingBy(
|
||
MetadataComponentIndex::getComponentType,
|
||
Collectors.counting()
|
||
));
|
||
|
||
ComponentTypeDistributionResponse response = new ComponentTypeDistributionResponse();
|
||
response.setDistribution(typeDistribution);
|
||
|
||
return response;
|
||
}
|
||
|
||
@Override
|
||
public ComponentVersionDistributionResponse getVersionDistribution(Long orgConfigId) {
|
||
QueryWrapper<MetadataComponentIndex> queryWrapper = new QueryWrapper<>();
|
||
List<MetadataComponentIndex> components = componentIndexMapper.selectList(queryWrapper);
|
||
|
||
Map<String, Long> versionDistribution = components.stream()
|
||
.collect(Collectors.groupingBy(
|
||
MetadataComponentIndex::getComponentVersion,
|
||
Collectors.counting()
|
||
));
|
||
|
||
ComponentVersionDistributionResponse response = new ComponentVersionDistributionResponse();
|
||
response.setDistribution(versionDistribution);
|
||
|
||
return response;
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 10. MetadataComponentParser 接口
|
||
|
||
```java
|
||
package com.datai.salesforce.metadata.component.parser;
|
||
|
||
import com.datai.salesforce.metadata.component.entity.MetadataComponentIndex;
|
||
|
||
import java.io.File;
|
||
import java.util.List;
|
||
|
||
public interface MetadataComponentParser {
|
||
|
||
List<MetadataComponentIndex> parse(File extractPath, Long taskId);
|
||
}
|
||
```
|
||
|
||
#### 11. ApexClassParser 实现类
|
||
|
||
```java
|
||
package com.datai.salesforce.metadata.component.parser;
|
||
|
||
import com.datai.salesforce.metadata.component.entity.MetadataComponentIndex;
|
||
import org.springframework.stereotype.Component;
|
||
|
||
import java.io.File;
|
||
import java.io.IOException;
|
||
import java.nio.file.Files;
|
||
import java.nio.file.Paths;
|
||
import java.util.ArrayList;
|
||
import java.util.List;
|
||
|
||
@Component
|
||
public class ApexClassParser implements MetadataComponentParser {
|
||
|
||
@Override
|
||
public List<MetadataComponentIndex> parse(File extractPath, Long taskId) {
|
||
List<MetadataComponentIndex> components = new ArrayList<>();
|
||
|
||
File apexClassesDir = new File(extractPath, "classes");
|
||
if (!apexClassesDir.exists()) {
|
||
return components;
|
||
}
|
||
|
||
File[] files = apexClassesDir.listFiles((dir, name) -> name.endsWith(".cls"));
|
||
if (files == null) {
|
||
return components;
|
||
}
|
||
|
||
for (File file : files) {
|
||
MetadataComponentIndex component = new MetadataComponentIndex();
|
||
component.setTaskId(taskId);
|
||
component.setComponentType("ApexClass");
|
||
component.setComponentName(file.getName().replace(".cls", ""));
|
||
component.setComponentVersion("1.0");
|
||
component.setFilePath(file.getAbsolutePath());
|
||
components.add(component);
|
||
}
|
||
|
||
return components;
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 12. MetadataComponentIndex 实体类
|
||
|
||
```java
|
||
package com.datai.salesforce.metadata.component.entity;
|
||
|
||
import com.baomidou.mybatisplus.annotation.IdType;
|
||
import com.baomidou.mybatisplus.annotation.TableId;
|
||
import com.baomidou.mybatisplus.annotation.TableName;
|
||
import lombok.Data;
|
||
|
||
import java.time.LocalDateTime;
|
||
|
||
@Data
|
||
@TableName("datai_metadata_component_index")
|
||
public class MetadataComponentIndex {
|
||
|
||
@TableId(type = IdType.AUTO)
|
||
private Long id;
|
||
|
||
private Long taskId;
|
||
|
||
private String componentType;
|
||
|
||
private String componentName;
|
||
|
||
private String componentVersion;
|
||
|
||
private String filePath;
|
||
|
||
private LocalDateTime createTime;
|
||
|
||
private LocalDateTime updateTime;
|
||
}
|
||
```
|
||
|
||
#### 13. MetadataComponentIndexMapper 接口
|
||
|
||
```java
|
||
package com.datai.salesforce.metadata.component.mapper;
|
||
|
||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||
import com.datai.salesforce.metadata.component.entity.MetadataComponentIndex;
|
||
import org.apache.ibatis.annotations.Mapper;
|
||
|
||
@Mapper
|
||
public interface MetadataComponentIndexMapper extends BaseMapper<MetadataComponentIndex> {
|
||
}
|
||
```
|
||
|
||
#### 14. DTO 类
|
||
|
||
```java
|
||
package com.datai.salesforce.metadata.component.dto;
|
||
|
||
import lombok.Data;
|
||
|
||
@Data
|
||
public class ComponentIndexRequest {
|
||
private Long taskId;
|
||
}
|
||
|
||
@Data
|
||
public class ComponentIndexResponse {
|
||
private Long taskId;
|
||
private Long total;
|
||
private String message;
|
||
}
|
||
|
||
@Data
|
||
public class ComponentQueryRequest {
|
||
private String type;
|
||
private String name;
|
||
private String version;
|
||
private int page;
|
||
private int size;
|
||
}
|
||
|
||
@Data
|
||
public class ComponentQueryResponse {
|
||
private long total;
|
||
private int page;
|
||
private int size;
|
||
private List<Object> records;
|
||
}
|
||
|
||
@Data
|
||
public class ComponentDetailResponse {
|
||
private Long id;
|
||
private Long taskId;
|
||
private String componentType;
|
||
private String componentName;
|
||
private String componentVersion;
|
||
private String filePath;
|
||
private LocalDateTime createTime;
|
||
}
|
||
|
||
@Data
|
||
public class ComponentStatisticsResponse {
|
||
private Long total;
|
||
}
|
||
|
||
@Data
|
||
public class ComponentTypeDistributionResponse {
|
||
private Map<String, Long> distribution;
|
||
}
|
||
|
||
@Data
|
||
public class ComponentVersionDistributionResponse {
|
||
private Map<String, Long> distribution;
|
||
}
|
||
```
|
||
|
||
#### 15. ComponentIndexException 异常类
|
||
|
||
```java
|
||
package com.datai.salesforce.metadata.component.exception;
|
||
|
||
public class ComponentIndexException extends RuntimeException {
|
||
|
||
public ComponentIndexException(String message) {
|
||
super(message);
|
||
}
|
||
|
||
public ComponentIndexException(String message, Throwable cause) {
|
||
super(message, cause);
|
||
}
|
||
}
|
||
```
|
||
|
||
## 约束
|
||
|
||
### 技术栈限制
|
||
|
||
- 必须基于 Spring Boot 3 + MyBatis Plus + MySQL 技术栈
|
||
- 必须使用现有的 IFileStorageService 接口进行文件读取
|
||
- 必须使用现有的文件存储和解压处理功能
|
||
|
||
### 架构约束
|
||
|
||
- 必须遵循 Authentication.canvas 中定义的架构和调用关系
|
||
- 必须在 datai-salesforce-metadata 模块下实现
|
||
- 必须使用 RESTful API 设计规范
|
||
|
||
### 性能要求
|
||
|
||
- 组件索引创建响应时间 < 5s
|
||
- 组件查询响应时间 < 1s
|
||
- 组件详情查看响应时间 < 500ms
|
||
- 组件统计响应时间 < 1s
|
||
|
||
### 安全性要求
|
||
|
||
- 组件索引和查询操作需要认证
|
||
- 文件读取需要权限控制
|
||
- 敏感信息不记录到日志
|
||
|
||
## Rule Set
|
||
|
||
"请严格参考 @Authentication.canvas 中的状态机转移逻辑,不要自行发挥。"
|
||
|
||
**具体规则**:
|
||
- 必须使用 Canvas 中定义的类名和方法名
|
||
- 必须遵循 Canvas 中定义的调用关系
|
||
- 必须参考 Canvas 中的流程图逻辑
|
||
- 必须复用现有的 IFileStorageService 接口
|
||
- 必须使用 MyBatis Plus 的 QueryWrapper 实现多条件查询
|
||
- 必须使用 MyBatis Plus 的分页插件实现分页查询
|
||
|
||
## 验收标准
|
||
|
||
### 功能完整性
|
||
|
||
- 组件索引创建成功,支持多种元数据类型解析
|
||
- 索引信息完整准确
|
||
- 索引创建性能满足要求
|
||
- 组件查询功能正常工作
|
||
- 支持按类型查询
|
||
- 支持按名称查询
|
||
- 支持按版本查询
|
||
- 支持多条件组合查询
|
||
- 支持分页查询
|
||
- API 接口符合 RESTful 规范
|
||
- 组件详情查看成功
|
||
- 组件信息完整准确
|
||
- 支持查看组件文件内容
|
||
- 支持查看组件依赖关系
|
||
- 组件统计功能正常工作
|
||
- 统计信息准确
|
||
- 支持按类型统计
|
||
- 支持按版本统计
|
||
- 支持按组织统计
|
||
|
||
### 代码正确性
|
||
|
||
- 代码符合项目编码规范,有清晰的注释
|
||
- 单元测试覆盖率 > 80%
|
||
- 集成测试通过率 100%
|
||
- 无严重的代码质量问题
|
||
|
||
### 文档准确性
|
||
|
||
- API 文档完整,包含接口说明、参数说明、返回值说明
|
||
- 代码注释清晰,包含方法说明、参数说明、返回值说明
|
||
- 使用文档完整,包含使用示例和注意事项
|
||
|
||
### 性能指标
|
||
|
||
- 组件索引创建响应时间 < 5s
|
||
- 组件查询响应时间 < 1s
|
||
- 组件详情查看响应时间 < 500ms
|
||
- 组件统计响应时间 < 1s
|
||
|
||
## 风险
|
||
|
||
### 输出质量风险
|
||
|
||
- 文件解析错误可能导致索引信息不准确
|
||
- 查询逻辑不完善可能导致查询结果不准确
|
||
- 统计逻辑错误可能导致统计信息不准确
|
||
|
||
### 技术实现风险
|
||
|
||
- 文件解析库选择不当可能导致解析错误
|
||
- 查询性能不佳可能影响用户体验
|
||
- 统计逻辑复杂可能导致实现困难
|
||
|
||
### 时间成本风险
|
||
|
||
- 元数据组件索引和查询功能实现可能需要较长时间
|
||
- 测试和验证可能需要较长时间
|
||
- 文档编写可能需要较长时间
|
||
|
||
## 使用记录
|
||
|
||
| 日期 | 使用场景 | 输入参数 | 输出结果 | 反馈 | 改进措施 |
|
||
|------|---------|---------|---------|------|----------|
|
||
| 2026-01-19 | 元数据组件索引和查询功能实现 | REQ-010-11, ADR-0020 | 元数据组件索引和查询功能代码 | 待反馈 | 待改进 |
|