- 完成REQ-010-17(性能优化和限流处理)的所有6个阶段 - 创建ADR文档:0026-performance-optimization.md - 创建Prompt文档:027-performance-optimization.md - 创建会话记录:20260119-performance-optimization.md - 创建变更记录:20260119-performance-optimization.md - 创建复盘报告:20260119-performance-optimization-retro.md - 更新index.md和CHANGELOG.md - 完成REQ-010-2(基础实体类和Mapper创建)的前3个阶段 - 更新ADR文档:0011-entity-mapper-create.md - 创建Prompt文档:002-entity-mapper-create.md - 更新index.md 所有文档均按照SSOT方法论创建,包括需求定义、架构决策、提示词资产化、执行会话、变更记录和闭环复盘。
744 lines
22 KiB
Markdown
744 lines
22 KiB
Markdown
# 元数据任务定义管理 - 实现提示词
|
|
|
|
## 提示词信息
|
|
|
|
- **提示词编号**: Prompt-014
|
|
- **创建日期**: 2026-01-18
|
|
- **相关需求**: [REQ-010-4](../requirements/REQ-010-4.md) - 元数据任务定义管理
|
|
- **相关决策**: [ADR-0013](../decisions/adr/0013-task-definition-management.md) - 元数据任务定义管理架构决策
|
|
|
|
## 输入引用
|
|
|
|
### 真源文档
|
|
|
|
- [REQ-010-4.md](../requirements/REQ-010-4.md) - 元数据任务定义管理需求文档
|
|
- [ADR-0013.md](../decisions/adr/0013-task-definition-management.md) - 元数据任务定义管理架构决策
|
|
- [metadata-module.md](../reference-code/com/docs/metadata-module.md) - Salesforce Metadata API 模块说明
|
|
- [file/index.md](../api-docs/file/index.md) - 文件模块 API 文档索引
|
|
|
|
### 技术规范
|
|
|
|
- Spring Boot 3 + Vue 3 技术栈
|
|
- MyBatis Plus 持久层框架
|
|
- RESTful API 设计规范
|
|
- 项目编码规范
|
|
|
|
## 提示词内容
|
|
|
|
### 角色设定
|
|
|
|
你是一个经验丰富的 Spring Boot 全栈开发工程师,专注于 Salesforce 元数据管理系统的开发。你熟悉以下技术栈:
|
|
|
|
- **后端**: Spring Boot 3, MyBatis Plus, MySQL
|
|
- **前端**: Vue 3, Element Plus
|
|
- **Salesforce API**: Metadata API, Partner API
|
|
- **工具**: Maven, Git, Postman
|
|
|
|
### 任务目标
|
|
|
|
实现元数据任务定义管理功能,包括:
|
|
|
|
1. **任务定义 CRUD 功能**
|
|
- 创建元数据任务
|
|
- 编辑元数据任务
|
|
- 删除元数据任务
|
|
- 查询元数据任务列表(支持分页和条件查询)
|
|
|
|
2. **package.xml 内容配置**
|
|
- 可视化编辑 package.xml 内容
|
|
- package.xml 格式验证
|
|
- 支持多种元数据类型配置
|
|
- 支持通配符配置
|
|
|
|
3. **API 版本选择**
|
|
- API 版本列表展示
|
|
- API 版本验证
|
|
- API 版本友好显示
|
|
|
|
4. **调度类型选择**
|
|
- 支持 Manual 和 Cron 两种调度类型
|
|
- 调度类型验证
|
|
- 调度类型友好显示
|
|
|
|
5. **Cron 表达式配置**
|
|
- Cron 表达式编辑
|
|
- Cron 表达式验证
|
|
- Cron 表达式预览
|
|
|
|
6. **任务验证功能**
|
|
- package.xml 格式验证
|
|
- Cron 表达式验证
|
|
- 验证失败返回详细错误信息
|
|
|
|
### 实现要求
|
|
|
|
#### 1. 数据模型
|
|
|
|
根据 ADR-0013 中定义的数据模型,创建以下实体类:
|
|
|
|
```java
|
|
@Data
|
|
@TableName("datai_meta_task")
|
|
public class DataiMetaTask {
|
|
@TableId(type = IdType.AUTO)
|
|
private Long id;
|
|
|
|
private String taskName;
|
|
|
|
private String taskType;
|
|
|
|
private Long orgConfigId;
|
|
|
|
@TableField(type = DbType.TEXT)
|
|
private String packageXml;
|
|
|
|
private String apiVersion;
|
|
|
|
private String scheduleType;
|
|
|
|
private String cronExpression;
|
|
|
|
private String status;
|
|
|
|
private String description;
|
|
|
|
private String createdBy;
|
|
|
|
private LocalDateTime createdTime;
|
|
|
|
private String updatedBy;
|
|
|
|
private LocalDateTime updatedTime;
|
|
}
|
|
```
|
|
|
|
#### 2. Mapper 接口
|
|
|
|
```java
|
|
@Mapper
|
|
public interface DataiMetaTaskMapper extends BaseMapper<DataiMetaTask> {
|
|
|
|
/**
|
|
* 查询任务列表
|
|
*/
|
|
IPage<DataiMetaTask> selectTaskPage(Page<DataiMetaTask> page, @Param("taskName") String taskName,
|
|
@Param("taskType") String taskType, @Param("status") String status);
|
|
|
|
/**
|
|
* 根据组织配置ID查询任务
|
|
*/
|
|
List<DataiMetaTask> selectByOrgConfigId(@Param("orgConfigId") Long orgConfigId);
|
|
}
|
|
```
|
|
|
|
#### 3. Service 层
|
|
|
|
```java
|
|
@Service
|
|
public class DataiMetaTaskServiceImpl implements IDataiMetaTaskService {
|
|
|
|
@Autowired
|
|
private DataiMetaTaskMapper taskMapper;
|
|
|
|
@Autowired
|
|
private PackageXmlValidator packageXmlValidator;
|
|
|
|
@Autowired
|
|
private CronExpressionValidator cronValidator;
|
|
|
|
/**
|
|
* 创建任务
|
|
*/
|
|
@Override
|
|
@Transactional
|
|
public Long createTask(DataiMetaTask task) {
|
|
// 验证 package.xml
|
|
ValidationResult xmlValidation = packageXmlValidator.validate(task.getPackageXml());
|
|
if (!xmlValidation.isSuccess()) {
|
|
throw new BusinessException(xmlValidation.getErrorMessage());
|
|
}
|
|
|
|
// 验证 Cron 表达式(如果是 Cron 调度)
|
|
if ("Cron".equals(task.getScheduleType())) {
|
|
ValidationResult cronValidation = cronValidator.validate(task.getCronExpression());
|
|
if (!cronValidation.isSuccess()) {
|
|
throw new BusinessException(cronValidation.getErrorMessage());
|
|
}
|
|
}
|
|
|
|
// 设置默认状态
|
|
task.setStatus("Active");
|
|
task.setCreatedTime(LocalDateTime.now());
|
|
task.setUpdatedTime(LocalDateTime.now());
|
|
|
|
// 保存任务
|
|
taskMapper.insert(task);
|
|
|
|
return task.getId();
|
|
}
|
|
|
|
/**
|
|
* 更新任务
|
|
*/
|
|
@Override
|
|
@Transactional
|
|
public void updateTask(DataiMetaTask task) {
|
|
// 验证 package.xml
|
|
ValidationResult xmlValidation = packageXmlValidator.validate(task.getPackageXml());
|
|
if (!xmlValidation.isSuccess()) {
|
|
throw new BusinessException(xmlValidation.getErrorMessage());
|
|
}
|
|
|
|
// 验证 Cron 表达式(如果是 Cron 调度)
|
|
if ("Cron".equals(task.getScheduleType())) {
|
|
ValidationResult cronValidation = cronValidator.validate(task.getCronExpression());
|
|
if (!cronValidation.isSuccess()) {
|
|
throw new BusinessException(cronValidation.getErrorMessage());
|
|
}
|
|
}
|
|
|
|
// 更新任务
|
|
task.setUpdatedTime(LocalDateTime.now());
|
|
taskMapper.updateById(task);
|
|
}
|
|
|
|
/**
|
|
* 删除任务
|
|
*/
|
|
@Override
|
|
@Transactional
|
|
public void deleteTask(Long id) {
|
|
taskMapper.deleteById(id);
|
|
}
|
|
|
|
/**
|
|
* 查询任务列表
|
|
*/
|
|
@Override
|
|
public IPage<DataiMetaTask> selectTaskPage(Integer pageNum, Integer pageSize, String taskName,
|
|
String taskType, String status) {
|
|
Page<DataiMetaTask> page = new Page<>(pageNum, pageSize);
|
|
QueryWrapper<DataiMetaTask> wrapper = new QueryWrapper<>();
|
|
|
|
if (StringUtils.isNotBlank(taskName)) {
|
|
wrapper.like("taskName", taskName);
|
|
}
|
|
if (StringUtils.isNotBlank(taskType)) {
|
|
wrapper.eq("taskType", taskType);
|
|
}
|
|
if (StringUtils.isNotBlank(status)) {
|
|
wrapper.eq("status", status);
|
|
}
|
|
|
|
wrapper.orderByDesc("createdTime");
|
|
|
|
return taskMapper.selectTaskPage(page, taskName, taskType, status);
|
|
}
|
|
|
|
/**
|
|
* 验证任务
|
|
*/
|
|
@Override
|
|
public ValidationResult validateTask(DataiMetaTask task) {
|
|
// 验证 package.xml
|
|
ValidationResult xmlValidation = packageXmlValidator.validate(task.getPackageXml());
|
|
if (!xmlValidation.isSuccess()) {
|
|
return xmlValidation;
|
|
}
|
|
|
|
// 验证 Cron 表达式(如果是 Cron 调度)
|
|
if ("Cron".equals(task.getScheduleType())) {
|
|
ValidationResult cronValidation = cronValidator.validate(task.getCronExpression());
|
|
if (!cronValidation.isSuccess()) {
|
|
return cronValidation;
|
|
}
|
|
}
|
|
|
|
return ValidationResult.success();
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 4. Controller 层
|
|
|
|
```java
|
|
@RestController
|
|
@RequestMapping("/metadata/task")
|
|
public class DataiMetaTaskController {
|
|
|
|
@Autowired
|
|
private IDataiMetaTaskService taskService;
|
|
|
|
/**
|
|
* 创建任务
|
|
*/
|
|
@PostMapping
|
|
public Result<Long> createTask(@Valid @RequestBody DataiMetaTask task) {
|
|
Long taskId = taskService.createTask(task);
|
|
return Result.success(taskId);
|
|
}
|
|
|
|
/**
|
|
* 更新任务
|
|
*/
|
|
@PutMapping("/{id}")
|
|
public Result<Void> updateTask(@PathVariable Long id, @Valid @RequestBody DataiMetaTask task) {
|
|
task.setId(id);
|
|
taskService.updateTask(task);
|
|
return Result.success();
|
|
}
|
|
|
|
/**
|
|
* 删除任务
|
|
*/
|
|
@DeleteMapping("/{id}")
|
|
public Result<Void> deleteTask(@PathVariable Long id) {
|
|
taskService.deleteTask(id);
|
|
return Result.success();
|
|
}
|
|
|
|
/**
|
|
* 查询任务列表
|
|
*/
|
|
@GetMapping("/list")
|
|
public Result<IPage<DataiMetaTask>> list(
|
|
@RequestParam(defaultValue = "1") Integer pageNum,
|
|
@RequestParam(defaultValue = "10") Integer pageSize,
|
|
@RequestParam(required = false) String taskName,
|
|
@RequestParam(required = false) String taskType,
|
|
@RequestParam(required = false) String status) {
|
|
IPage<DataiMetaTask> page = taskService.selectTaskPage(pageNum, pageSize, taskName, taskType, status);
|
|
return Result.success(page);
|
|
}
|
|
|
|
/**
|
|
* 查询任务详情
|
|
*/
|
|
@GetMapping("/{id}")
|
|
public Result<DataiMetaTask> getTask(@PathVariable Long id) {
|
|
DataiMetaTask task = taskService.getById(id);
|
|
return Result.success(task);
|
|
}
|
|
|
|
/**
|
|
* 验证任务
|
|
*/
|
|
@PostMapping("/{id}/validate")
|
|
public Result<ValidationResult> validateTask(@PathVariable Long id) {
|
|
DataiMetaTask task = taskService.getById(id);
|
|
ValidationResult result = taskService.validateTask(task);
|
|
return Result.success(result);
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 5. package.xml 验证器
|
|
|
|
```java
|
|
@Component
|
|
public class PackageXmlValidator {
|
|
|
|
private static final List<String> SUPPORTED_METADATA_TYPES = Arrays.asList(
|
|
"CustomObject", "CustomField", "ApexClass", "ApexTrigger",
|
|
"Layout", "Workflow", "ValidationRule", "Flow"
|
|
);
|
|
|
|
public ValidationResult validate(String packageXml) {
|
|
try {
|
|
// 解析 XML
|
|
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
|
DocumentBuilder builder = factory.newDocumentBuilder();
|
|
Document doc = builder.parse(new InputSource(new StringReader(packageXml)));
|
|
|
|
// 验证根元素
|
|
NodeList types = doc.getElementsByTagName("types");
|
|
if (types.getLength() == 0) {
|
|
return ValidationResult.error("package.xml 必须包含 types 元素");
|
|
}
|
|
|
|
// 验证元数据类型
|
|
for (int i = 0; i < types.getLength(); i++) {
|
|
Element type = (Element) types.item(i);
|
|
String typeName = type.getTextContent();
|
|
if (!isSupportedMetadataType(typeName)) {
|
|
return ValidationResult.error("不支持的元数据类型: " + typeName);
|
|
}
|
|
}
|
|
|
|
return ValidationResult.success();
|
|
} catch (Exception e) {
|
|
return ValidationResult.error("package.xml 格式错误: " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
private boolean isSupportedMetadataType(String typeName) {
|
|
return SUPPORTED_METADATA_TYPES.contains(typeName);
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 6. Cron 表达式验证器
|
|
|
|
```java
|
|
@Component
|
|
public class CronExpressionValidator {
|
|
|
|
public ValidationResult validate(String cronExpression) {
|
|
try {
|
|
// 使用 Quartz 的 CronExpression 验证
|
|
CronExpression cron = new CronExpression(cronExpression);
|
|
|
|
// 验证是否有效
|
|
if (!cron.isValid()) {
|
|
return ValidationResult.error("Cron 表达式格式错误");
|
|
}
|
|
|
|
// 验证是否能够计算下次执行时间
|
|
Date nextValidTime = cron.getNextValidTimeAfter(new Date());
|
|
if (nextValidTime == null) {
|
|
return ValidationResult.error("Cron 表达式无法计算下次执行时间");
|
|
}
|
|
|
|
return ValidationResult.success(nextValidTime);
|
|
} catch (Exception e) {
|
|
return ValidationResult.error("Cron 表达式解析错误: " + e.getMessage());
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 7. 前端组件
|
|
|
|
```vue
|
|
<template>
|
|
<div class="task-manager">
|
|
<el-card>
|
|
<template #header>
|
|
<span>元数据任务管理</span>
|
|
<el-button type="primary" @click="showCreateDialog">创建任务</el-button>
|
|
</template>
|
|
|
|
<!-- 搜索表单 -->
|
|
<el-form :inline="true" :model="searchForm">
|
|
<el-form-item label="任务名称">
|
|
<el-input v-model="searchForm.taskName" placeholder="请输入任务名称" />
|
|
</el-form-item>
|
|
<el-form-item label="任务类型">
|
|
<el-select v-model="searchForm.taskType" placeholder="请选择任务类型">
|
|
<el-option label="拉取" value="retrieve" />
|
|
<el-option label="部署" value="deploy" />
|
|
</el-select>
|
|
</el-form-item>
|
|
<el-form-item>
|
|
<el-button type="primary" @click="handleSearch">查询</el-button>
|
|
<el-button @click="handleReset">重置</el-button>
|
|
</el-form-item>
|
|
</el-form>
|
|
|
|
<!-- 任务列表 -->
|
|
<el-table :data="taskList" border>
|
|
<el-table-column prop="taskName" label="任务名称" />
|
|
<el-table-column prop="taskType" label="任务类型">
|
|
<template #default="{ row }">
|
|
<el-tag v-if="row.taskType === 'retrieve'" type="success">拉取</el-tag>
|
|
<el-tag v-else type="warning">部署</el-tag>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="scheduleType" label="调度类型" />
|
|
<el-table-column prop="status" label="状态">
|
|
<template #default="{ row }">
|
|
<el-tag v-if="row.status === 'Active'" type="success">启用</el-tag>
|
|
<el-tag v-else type="info">禁用</el-tag>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="createdTime" label="创建时间" />
|
|
<el-table-column label="操作" width="300">
|
|
<template #default="{ row }">
|
|
<el-button size="small" @click="handleEdit(row)">编辑</el-button>
|
|
<el-button size="small" type="danger" @click="handleDelete(row)">删除</el-button>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
|
|
<!-- 分页 -->
|
|
<el-pagination
|
|
v-model:current-page="pagination.pageNum"
|
|
v-model:page-size="pagination.pageSize"
|
|
:total="pagination.total"
|
|
@current-change="handlePageChange"
|
|
@size-change="handleSizeChange"
|
|
/>
|
|
</el-card>
|
|
|
|
<!-- 创建/编辑对话框 -->
|
|
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="80%">
|
|
<el-form :model="taskForm" :rules="formRules" ref="taskFormRef">
|
|
<el-form-item label="任务名称" prop="taskName">
|
|
<el-input v-model="taskForm.taskName" placeholder="请输入任务名称" />
|
|
</el-form-item>
|
|
<el-form-item label="任务类型" prop="taskType">
|
|
<el-select v-model="taskForm.taskType" placeholder="请选择任务类型">
|
|
<el-option label="拉取" value="retrieve" />
|
|
<el-option label="部署" value="deploy" />
|
|
</el-select>
|
|
</el-form-item>
|
|
<el-form-item label="组织配置" prop="orgConfigId">
|
|
<el-select v-model="taskForm.orgConfigId" placeholder="请选择组织配置">
|
|
<el-option
|
|
v-for="org in orgList"
|
|
:key="org.id"
|
|
:label="org.orgName"
|
|
:value="org.id"
|
|
/>
|
|
</el-select>
|
|
</el-form-item>
|
|
<el-form-item label="package.xml" prop="packageXml">
|
|
<el-input
|
|
v-model="taskForm.packageXml"
|
|
type="textarea"
|
|
:rows="10"
|
|
placeholder="请输入 package.xml 内容"
|
|
/>
|
|
</el-form-item>
|
|
<el-form-item label="API 版本" prop="apiVersion">
|
|
<el-select v-model="taskForm.apiVersion" placeholder="请选择 API 版本">
|
|
<el-option label="58.0" value="58.0" />
|
|
<el-option label="57.0" value="57.0" />
|
|
<el-option label="56.0" value="56.0" />
|
|
</el-select>
|
|
</el-form-item>
|
|
<el-form-item label="调度类型" prop="scheduleType">
|
|
<el-select v-model="taskForm.scheduleType" placeholder="请选择调度类型">
|
|
<el-option label="手动" value="Manual" />
|
|
<el-option label="Cron" value="Cron" />
|
|
</el-select>
|
|
</el-form-item>
|
|
<el-form-item label="Cron 表达式" prop="cronExpression" v-if="taskForm.scheduleType === 'Cron'">
|
|
<el-input v-model="taskForm.cronExpression" placeholder="请输入 Cron 表达式" />
|
|
<div class="cron-preview">
|
|
下次执行时间: {{ cronPreview }}
|
|
</div>
|
|
</el-form-item>
|
|
<el-form-item label="任务描述">
|
|
<el-input
|
|
v-model="taskForm.description"
|
|
type="textarea"
|
|
:rows="3"
|
|
placeholder="请输入任务描述"
|
|
/>
|
|
</el-form-item>
|
|
</el-form>
|
|
<template #footer>
|
|
<el-button @click="dialogVisible = false">取消</el-button>
|
|
<el-button type="primary" @click="handleSave">保存</el-button>
|
|
<el-button type="info" @click="handleValidate">验证</el-button>
|
|
</template>
|
|
</el-dialog>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, reactive, computed } from 'vue';
|
|
import { ElMessage } from 'element-plus';
|
|
|
|
const taskList = ref([]);
|
|
const dialogVisible = ref(false);
|
|
const dialogTitle = ref('创建任务');
|
|
const taskFormRef = ref(null);
|
|
const searchForm = reactive({
|
|
taskName: '',
|
|
taskType: '',
|
|
status: ''
|
|
});
|
|
const taskForm = reactive({
|
|
id: null,
|
|
taskName: '',
|
|
taskType: 'retrieve',
|
|
orgConfigId: null,
|
|
packageXml: '',
|
|
apiVersion: '58.0',
|
|
scheduleType: 'Manual',
|
|
cronExpression: '',
|
|
description: ''
|
|
});
|
|
const pagination = reactive({
|
|
pageNum: 1,
|
|
pageSize: 10,
|
|
total: 0
|
|
});
|
|
const orgList = ref([]);
|
|
|
|
const cronPreview = computed(() => {
|
|
// 计算 Cron 表达式的下次执行时间
|
|
if (taskForm.scheduleType === 'Cron' && taskForm.cronExpression) {
|
|
// 调用后端 API 计算
|
|
return '计算中...';
|
|
}
|
|
return '';
|
|
});
|
|
|
|
const formRules = {
|
|
taskName: [{ required: true, message: '请输入任务名称', trigger: 'blur' }],
|
|
taskType: [{ required: true, message: '请选择任务类型', trigger: 'change' }],
|
|
orgConfigId: [{ required: true, message: '请选择组织配置', trigger: 'change' }],
|
|
packageXml: [{ required: true, message: '请输入 package.xml 内容', trigger: 'blur' }],
|
|
apiVersion: [{ required: true, message: '请选择 API 版本', trigger: 'change' }],
|
|
scheduleType: [{ required: true, message: '请选择调度类型', trigger: 'change' }],
|
|
cronExpression: [{ required: true, message: '请输入 Cron 表达式', trigger: 'blur' }]
|
|
};
|
|
|
|
const handleSearch = () => {
|
|
// 查询任务列表
|
|
};
|
|
|
|
const handleReset = () => {
|
|
searchForm.taskName = '';
|
|
searchForm.taskType = '';
|
|
searchForm.status = '';
|
|
handleSearch();
|
|
};
|
|
|
|
const showCreateDialog = () => {
|
|
dialogTitle.value = '创建任务';
|
|
Object.assign(taskForm, {
|
|
id: null,
|
|
taskName: '',
|
|
taskType: 'retrieve',
|
|
orgConfigId: null,
|
|
packageXml: '',
|
|
apiVersion: '58.0',
|
|
scheduleType: 'Manual',
|
|
cronExpression: '',
|
|
description: ''
|
|
});
|
|
dialogVisible.value = true;
|
|
};
|
|
|
|
const handleEdit = (row) => {
|
|
dialogTitle.value = '编辑任务';
|
|
Object.assign(taskForm, row);
|
|
dialogVisible.value = true;
|
|
};
|
|
|
|
const handleDelete = (row) => {
|
|
ElMessage.confirm('确定要删除该任务吗?', '提示', {
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消',
|
|
type: 'warning'
|
|
}).then(() => {
|
|
// 调用删除 API
|
|
ElMessage.success('删除成功');
|
|
handleSearch();
|
|
});
|
|
};
|
|
|
|
const handleSave = () => {
|
|
taskFormRef.value.validate((valid) => {
|
|
if (valid) {
|
|
// 调用保存 API
|
|
ElMessage.success('保存成功');
|
|
dialogVisible.value = false;
|
|
handleSearch();
|
|
}
|
|
});
|
|
};
|
|
|
|
const handleValidate = () => {
|
|
// 调用验证 API
|
|
};
|
|
|
|
const handlePageChange = (pageNum) => {
|
|
pagination.pageNum = pageNum;
|
|
handleSearch();
|
|
};
|
|
|
|
const handleSizeChange = (pageSize) => {
|
|
pagination.pageSize = pageSize;
|
|
handleSearch();
|
|
};
|
|
</script>
|
|
|
|
<style scoped>
|
|
.task-manager {
|
|
padding: 20px;
|
|
}
|
|
.cron-preview {
|
|
margin-top: 10px;
|
|
padding: 10px;
|
|
background-color: #f5f7fa;
|
|
border-radius: 4px;
|
|
}
|
|
</style>
|
|
```
|
|
|
|
### 输出格式
|
|
|
|
#### 1. 代码结构
|
|
|
|
```
|
|
datai-salesforce-metadata/
|
|
├── src/main/java/com/datai/metadata/
|
|
│ ├── controller/
|
|
│ │ └── DataiMetaTaskController.java
|
|
│ ├── service/
|
|
│ │ ├── IDataiMetaTaskService.java
|
|
│ │ └── impl/
|
|
│ │ └── DataiMetaTaskServiceImpl.java
|
|
│ ├── mapper/
|
|
│ │ └── DataiMetaTaskMapper.java
|
|
│ ├── entity/
|
|
│ │ └── DataiMetaTask.java
|
|
│ └── validator/
|
|
│ ├── PackageXmlValidator.java
|
|
│ └── CronExpressionValidator.java
|
|
└── src/main/resources/
|
|
└── mapper/
|
|
└── DataiMetaTaskMapper.xml
|
|
```
|
|
|
|
#### 2. 单元测试
|
|
|
|
必须为以下类编写单元测试:
|
|
|
|
- DataiMetaTaskServiceImpl
|
|
- PackageXmlValidator
|
|
- CronExpressionValidator
|
|
- DataiMetaTaskController
|
|
|
|
#### 3. 集成测试
|
|
|
|
必须编写以下集成测试:
|
|
|
|
- 任务 CRUD 操作
|
|
- package.xml 验证
|
|
- Cron 表达式验证
|
|
- API 接口测试
|
|
|
|
#### 4. API 文档
|
|
|
|
必须为以下接口编写 API 文档:
|
|
|
|
- POST /metadata/task - 创建任务
|
|
- PUT /metadata/task/{id} - 更新任务
|
|
- DELETE /metadata/task/{id} - 删除任务
|
|
- GET /metadata/task/list - 查询任务列表
|
|
- GET /metadata/task/{id} - 查询任务详情
|
|
- POST /metadata/task/{id}/validate - 验证任务
|
|
|
|
### 注意事项
|
|
|
|
1. **package.xml 存储**: 使用 TEXT 类型存储,避免 VARCHAR 长度限制
|
|
2. **Cron 表达式**: 使用 Quartz 库进行验证,确保格式正确
|
|
3. **事务管理**: 创建、更新、删除操作必须使用 @Transactional 注解
|
|
4. **参数验证**: 使用 @Valid 注解进行参数验证
|
|
5. **异常处理**: 使用统一的异常处理机制,返回友好的错误信息
|
|
6. **日志记录**: 记录关键操作的日志,便于问题排查
|
|
7. **权限控制**: 根据用户权限控制任务的访问和操作
|
|
|
|
### 参考资料
|
|
|
|
- [REQ-010-4.md](../requirements/REQ-010-4.md) - 元数据任务定义管理需求
|
|
- [ADR-0013.md](../decisions/adr/0013-task-definition-management.md) - 元数据任务定义管理架构决策
|
|
- [metadata-module.md](../reference-code/com/docs/metadata-module.md) - Salesforce Metadata API 模块说明
|
|
- [Authentication.canvas](../Authentication.canvas) - 项目架构视觉化展示
|