【AI4CODE】目录
【AI4CODE】2 Trae 锤一个 To-Do-List
应用场景就是从一个 REST API GET 到数据后,经过数据转换 POST 到另一个 REST API。用 Trae CN 折腾了 3 天终于搞成功了,记录一下,好脑瓜不如烂笔头。
1 构建提示词
1.1 构建整个框架提示词
# 0 数据搬运工 提示词
## 1 应用名称:数据搬运工
## 2 开发代号:DataHauler
## 3 功能包括
- 源端API数据定义:可请求方式,定义URL,请求头headers,请求数据负载 payload,还有测试按钮 请求成功获取 json格式定义的数据
- 目标端API数据定义:可请求方式,定义URL,请求头headers,请求数据负载 payload,还有测试按钮
- 数据对照关系定义:目标端API负载的json数据和源端API数据获取Json数据对照关系定义
- 数据搬运按钮:点击执行数据搬运操作,也可以设置时间周期自动执行搬运
## 4 技术栈: 采用 html+css+javascript的技术栈
## 5 托管部署: 可托管部署在csdn的inscode上
## 6 UI要求: 简洁美观
1.2 开始搬运按钮提示词
7 开始搬运按钮的代码逻辑
- 执行【源端测试连接】按钮上代码,获取源端API的响应数据后;
- 源端响应数据如下:
json { "data": { "rows": [ { "DATE_T": "2025-03-27T13:41:43+08:00", "N_AGE": 55, "P_ID": -300, "S_DATE": "2025-03-27", "S_NAME": "5217" }, { "DATE_T": "2024-04-09T00:00:00+08:00", "N_AGE": 17, "P_ID": 1, "S_DATE": "2024-04-08", "S_NAME": "blma" }, { "DATE_T": "2024-04-09T17:01:36+08:00", "N_AGE": 52, "P_ID": 2, "S_DATE": "2024-04-09", "S_NAME": "白龙马" } ] }, "msg": "", "status": 0, "total": 3 }
- 按照映射配置定义的json数据结构 ```json { “P_ID2”: “data.rows[1].P_ID”, “S_NAME2”: “data.rows[1].S_NAME”, “N_AGE2”: “data.rows[1].N_AGE” }
4. 以及目标端请求数据负载模版 ```json { "P_ID2": 222, "S_NAME2": "blmA", "N_AGE2": 56 } ``` 逐行构造目标端API的负载数据 5. 执行【目标端测试连接】按钮上代码 6. 重复执行3-5步
1.3 定时搬运提示词
## 9 V7版本修改为可以定时搬运数据
scheduleTransfer()倒计时结束 直接调用 scheduleTransfer()实现定时搬运数据
在【定时搬运】按钮上显示倒计时
1.4 补充说明
-
首先我的前端三件套(HTML+CSS+JavaScript)是很菜的,很多都是现学现问的。
-
后端用的 Goland 开发的通用后端 REST2SQL 简单配置一下数据库连接字符串就可以提供 所有数据库表和视图的 REST 服务,甚至是直接执行SQL。
-
前端服务用在 Trae 下安装的 live-server 插件
-
整个都是用的 Builder 模式,构建过程不是很顺利,经常翻车,有时候是直接拷贝代码为 Trae 来修改,修改多次都不能满意就亲自上手,用的多了就知道如何用自然语言和 Trae 交互了。
2 数据搬运工的全部代码
2.1 index.html
页面布局
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数据搬运工 - DataHauler</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<h1>数据搬运工</h1>
<div class="config-container">
<!-- 源端API配置 -->
<div class="api-config source-config">
<h2>源端API配置</h2>
<form id="sourceApiForm">
<div class="form-group">
<label for="sourceUrl">请求方法和API地址:</label>
<div class="form-group row">
<select id="sourceMethod" required>
<option value="GET" selected>GET</option>
<option value="POST">POST</option>
<option value="PUT">PUT</option>
<option value="DELETE">DELETE</option>
</select>
<input type="text" id="sourceUrl" placeholder="http://127.0.0.1:5217/rest/dataTable" required>
</div>
</div>
<div class="form-group">
<label for="sourceHeaders">请求头:</label>
<textarea id="sourceHeaders" rows="3" placeholder="{}" Authorization\": \"Bearer token\"}"></textarea>
</div>
<div class="form-group">
<label for="sourcePayload">请求负载:</label>
<textarea id="sourcePayload" rows="3" placeholder="{}" param1\": \"value1\"}"></textarea>
</div>
<button type="button" id="testSourceApi">源端测试连接</button>
<div class="form-group">
<label for="sourceResponse">响应数据:</label>
<textarea id="sourceResponse" rows="5" placeholder="源端API响应数据将显示在这里" readonly></textarea>
</div>
</form>
</div>
<!-- 目标端API配置 -->
<div class="api-config target-config">
<h2>目标端API配置</h2>
<form id="targetApiForm">
<div class="form-group">
<label for="targetUrl">请求方法和API地址:</label>
<div class="form-group row">
<select id="targetMethod" required>
<option value="GET">GET</option>
<option value="POST" selected>POST</option>
<option value="PUT">PUT</option>
<option value="DELETE">DELETE</option>
</select>
<input type="text" id="targetUrl" placeholder="https://api.example.com/insert" required>
</div>
</div>
<div class="form-group">
<label for="targetHeaders">请求头:</label>
<textarea id="targetHeaders" rows="3" placeholder="{}" Content-Type\": \"application/json\"}"></textarea>
</div>
<div class="form-group">
<label for="targetPayload">请求负载模板:</label>
<textarea id="targetPayload" rows="3" placeholder="{}" data\": \"{{sourceData}}\"}"></textarea>
</div>
<button type="button" id="testTargetApi">目标端测试连接</button>
<div class="form-group">
<label for="targetResponse">响应数据:</label>
<textarea id="targetResponse" rows="5" placeholder="目标端API响应数据将显示在这里" readonly></textarea>
</div>
</form>
</div>
</div>
<!-- 数据映射配置 -->
<div id="mappingEditor" class="mapping-config">
<h2>数据映射关系</h2>
<div class="form-group">
<textarea id="mappingContent" rows="10"
placeholder='[{"P_ID2": "data.rows[0].P_ID","S_NAME2": "data.rows[0].S_NAME","N_AGE2": "data.rows[0].N_AGE"}]'
class="json-editor"></textarea>
</div>
</div>
<div style="text-align:center; margin: 10px 40px;">
<button type="button" id="loadFromLocal">本地加载配置</button>
<button type="button" id="saveAllConfig">保存当前配置</button>
</div>
</div>
<!-- 操作按钮 -->
<div class="actions">
<button id="startTransfer">开始搬运</button>
<button id="scheduleTransfer">定时搬运</button>
</div>
</div>
<script src="app.js"></script>
</body>
</html>
2.2 style.css
CSS样式
/* 基础样式重置 */
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Segoe UI', system-ui, sans-serif;
line-height: 1;
padding: 5px;
background-color: #f8f9fa;
color: #333;
}
h1 {
text-align: center;
margin: 0rem 0;
padding: 1rem 0;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 15px;
background: white;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.config-container h2 {
text-align: center;
margin: 1.5rem 0;
padding: 0.5rem;
font-size: 1.5rem;
}
/* 三栏布局样式 */
.config-container {
display: flex;
gap: 15px;
margin-bottom: 1rem;
}
.api-config {
flex: 1;
}
.api-config {
flex: 1;
padding: 5px;
background: white;
border: 1px solid #e0e0e0;
border-radius: 8px;
margin-bottom: 5px;
display: flex;
flex-direction: column;
gap: 10px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
}
.mapping-config {
margin-top: 1rem;
}
.actions {
display: flex;
gap: 1rem;
justify-content: center;
margin-top: 2rem;
}
.source-config {
order: 1;
flex: 1;
}
.target-config {
order: 2;
flex: 1;
}
/* 表单样式 */
.form-group {
margin-bottom: 0.1rem;
display: flex;
flex-direction: column;
gap: 0.05rem;
}
.form-group.row {
flex-direction: row;
align-items: center;
}
.form-group.row select {
flex: 0.5;
margin-right: 10px;
}
.form-group.row input {
flex: 5;
}
.form-group label {
font-weight: 600;
color: #555;
}
input,
textarea {
padding: 0.8rem;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 1rem;
font-family: Consolas, monospace;
}
textarea {
min-height: 100px;
resize: vertical;
}
#sourceResponse,
#targetResponse {
min-height: 120px;
}
/* 按钮样式 */
button {
padding: 0.5rem 3rem;
border: none;
border-radius: 5px;
cursor: pointer;
transition: all 0.2s;
font-weight: 600;
}
#testSourceApi,
#testTargetApi {
background: #576b95;
color: white;
}
#testSourceApi:hover,
#testTargetApi:hover {
opacity: 0.9;
}
/* 数据映射区域 */
.mapping-config {
margin-bottom: 1rem;
padding: 1rem;
border: 1px solid #eee;
border-radius: 8px;
}
/* 操作按钮区域 */
.actions {
display: flex;
gap: 30rem;
justify-content: center;
}
#startTransfer {
background: #07c160;
color: white;
padding: 10px 80px;
border-radius: 25px;
box-shadow: 0 2px 6px rgba(7, 193, 96, 0.3);
}
#testSourceApi {
display: block;
margin: 0.5rem auto;
text-align: center;
}
#testTargetApi {
display: block;
margin: 0.5rem auto;
text-align: center;
}
#scheduleTransfer {
background: #6467f2;
color: white;
padding: 10px 50px;
}
#startTransfer:hover,
#scheduleTransfer:hover {
opacity: 0.9;
}
2.3 app.js
代码逻辑
// 数据搬运工核心功能
class DataHauler {
constructor() {
this.sourceApi = {
method:'',
url: '',
headers: {},
payload: {}
};
this.targetApi = {
method:'',
url: '',
headers: {},
payloadTemplate: ''
};
// 初始化表单默认值
document.getElementById('sourceHeaders').value = '{}';
document.getElementById('sourcePayload').value = '{}';
document.getElementById('targetHeaders').value = '{}';
document.getElementById('targetPayload').value = '{}';
document.getElementById('mappingContent').value = '{}';
this.mappings = {};
// 初始化事件监听
this.initEventListeners();
// 添加API配置文件输入元素
const configFileInput = document.createElement('input');
configFileInput.type = 'file';
configFileInput.accept = '.json';
configFileInput.style.display = 'none';
configFileInput.addEventListener('change', (e) => this.loadConfigFromFile(e));
document.body.appendChild(configFileInput);
// 移除保存API配置按钮
const saveApiBtn = document.querySelector('.button-group button:first-child');
if (saveApiBtn && saveApiBtn.textContent === '保存API配置') {
saveApiBtn.remove();
}
// 绑定从本地加载按钮事件
document.getElementById('loadFromLocal').addEventListener('click', () => {
const choice = confirm('确定要加载全部配置吗?\n\n确定 - 加载全部配置\n取消 - 不加载');
if (choice) {
//apiConfigFileInput.click();
configFileInput.click();
}
});
}
// 初始化事件监听
initEventListeners() {
// 测试源端API连接
document.getElementById('testSourceApi').addEventListener('click', () => {
this.testSourceApi();
});
// 测试目标端API连接
document.getElementById('testTargetApi').addEventListener('click', () => {
this.testTargetApi();
});
// 开始搬运数据
document.getElementById('startTransfer').addEventListener('click', () => {
this.startTransfer();
});
// 定时搬运数据
document.getElementById('scheduleTransfer').addEventListener('click', () => {
this.scheduleTransfer();
});
}
// 测试源端API连接
async testSourceApi() {
try {
// 获取表单数据
const sourceUrl = document.getElementById('sourceUrl').value.trim();
if (!sourceUrl) {
throw new Error('请填写源端API地址');
}
this.sourceApi.url = sourceUrl;
// 解析请求头JSON
const headersValue = document.getElementById('sourceHeaders').value.trim();
this.sourceApi.headers = headersValue ? JSON.parse(headersValue) : {};
// 解析请求负载JSON
const payloadValue = document.getElementById('sourcePayload').value.trim();
this.sourceApi.payload = payloadValue ? JSON.parse(payloadValue) : {};
// 获取请求方法
this.sourceApi.method = document.getElementById('sourceMethod').value;
// 调用API
const requestOptions = {
method: this.sourceApi.method,
headers: this.sourceApi.headers
};
// 只有非GET请求才需要body
if (this.sourceApi.method !== 'GET' && Object.keys(this.sourceApi.payload).length > 0) {
requestOptions.body = JSON.stringify(this.sourceApi.payload);
}
const response = await this.callApi(this.sourceApi.url, requestOptions);
// 检查返回数据是否有效
if (!response) {
throw new Error('返回数据不能为空');
}
let formattedResponse;
// 处理不同类型的响应数据
if (typeof response === 'string') {
try {
// 尝试解析为JSON
const parsed = JSON.parse(response);
formattedResponse = JSON.stringify(parsed, null, 2);
} catch (e) {
// 如果不是JSON,直接显示原始字符串
formattedResponse = response;
}
} else if (typeof response === 'object') {
// 如果是对象,格式化为JSON字符串
formattedResponse = JSON.stringify(response, null, 2);
} else {
// 其他类型转换为字符串
formattedResponse = String(response);
}
document.getElementById('sourceResponse').value = typeof formattedResponse === 'string' ? formattedResponse.replace(/\\"/g, '"') : JSON.stringify(formattedResponse, null, 2).replace(/\\"/g, '"');
return response; // 返回数据用于后续处理
} catch (error) {
document.getElementById('sourceResponse').value = `错误: ${error.message}`;
throw error; // 重新抛出错误以便外部捕获
}
}
// 测试目标端API连接
async testTargetApi() {
try {
// 获取表单数据
this.targetApi.url = document.getElementById('targetUrl').value;
this.targetApi.headers = JSON.parse(document.getElementById('targetHeaders').value || '{}');
this.targetApi.payloadTemplate = document.getElementById('targetPayload').value;
this.targetApi.method = document.getElementById('targetMethod').value;
// 调用API
const response = await this.callApi(this.targetApi.url, {
method: this.targetApi.method,
headers: this.targetApi.headers,
body: this.targetApi.payloadTemplate
});
// 将响应数据显示在目标端响应框中
document.getElementById('targetResponse').value = typeof response === 'string' ? response : JSON.stringify(response, null, 2).replace(/\\"/g, '"');
} catch (error) {
document.getElementById('targetResponse').value = `错误: ${error.message}`;
}
}
// 开始搬运数据
async startTransfer() {
try {
// 1. 测试源端API
const sourceData = await this.testSourceApi();
// 2. 遍历源数据行并应用映射
const parsed = JSON.parse(sourceData);
// 从映射配置中动态获取rows路径
const firstMapping = Object.values(this.mappings)[0];
const rowsPathMatch = firstMapping.match(/data\.(rows\[\d+\]|rows)/);
const rowsPath = rowsPathMatch ? rowsPathMatch[0] : 'data.rows'; // 使用匹配到的路径或默认路径
// 动态获取rows数组
const rows = rowsPath.split('.').reduce((obj, key) => {
// 去除数组索引部分,只保留属性名
const cleanKey = key.replace(/\[\d+\]/g, '');
return obj?.[cleanKey];
}, parsed) || [];
for (const row of rows) {
// 3. 应用数据映射
const transformedData = {};
for (const [targetKey, sourcePath] of Object.entries(this.mappings)) {
const pathParts = sourcePath.split('.');
let value = row;
for (const part of pathParts.slice(2)) { // 跳过data.rows部分
if (part.includes('[')) {
const arrayPart = part.replace(/\[\d+\]/g, '');
value = value[arrayPart];
} else {
value = value[part];
}
}
transformedData[targetKey] = value;
}
// alert(`成功应用数据映射: ${JSON.stringify(transformedData)}`);
// 5. 发送到目标端
this.targetApi.method = document.getElementById('targetMethod').value;
this.targetApi.url = document.getElementById('targetUrl').value;
this.targetApi.headers = JSON.parse(document.getElementById('targetHeaders').value || '{}');
//this.targetApi.payloadTemplate = targetPayload;
document.getElementById('targetPayload').value = JSON.stringify(transformedData, null, 2);
const response = await this.callApi(this.targetApi.url, {
method: this.targetApi.method,
headers: this.targetApi.headers,
body: JSON.stringify(transformedData)
});
console.log(`成功搬运数据行: ${JSON.stringify(row)}`);
}
console.log(`${new Date()}数据搬运完成!共处理${rows.length}条记录`);
} catch (error) {
alert(`数据搬运失败: ${error.message}`);
}
}
// 定时搬运数据
scheduleTransfer() {
// 清除现有的定时器和倒计时
if (this.timers) {
clearInterval(this.timers.transfer);
clearInterval(this.timers.countdown);
}
const interval = prompt('请输入定时间隔(分钟):', '5217');
if (interval && !isNaN(interval)) {
const minutes = parseInt(interval);
const intervalMs = minutes * 60 * 1000;
const button = document.getElementById('scheduleTransfer');
// 立即执行一次
this.startTransfer();
// 设置定时器
const timerId = setInterval(() => this.startTransfer(), intervalMs);
// 更新按钮文本显示倒计时
let remaining = minutes * 60;
const updateButtonText = () => {
const hours = Math.floor(remaining / 3600);
const mins = Math.floor((remaining % 3600) / 60);
const secs = remaining % 60;
button.textContent = `定时搬运 (${hours}:${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')})`;
};
updateButtonText();
// 每秒更新倒计时
const countdown = setInterval(() => {
remaining--;
updateButtonText();
if (remaining <= 0) {
remaining = minutes * 60;
}
}, 1000);
// 存储定时器ID以便后续清除
this.timers = {
transfer: timerId,
countdown: countdown
};
}
}
// 加载API配置和映射配置
async loadConfigFromFile(event) {
try {
const file = event.target.files[0];
if (!file) {
return;
}
const reader = new FileReader();
reader.onload = (e) => {
try {
const config = JSON.parse(e.target.result);
// 设置API配置
if (config.sourceApi) {
document.getElementById('sourceMethod').value = config.sourceApi.method;
document.getElementById('sourceUrl').value = config.sourceApi.url;
document.getElementById('sourceHeaders').value = JSON.stringify(config.sourceApi.headers, null, 2);
document.getElementById('sourcePayload').value = JSON.stringify(config.sourceApi.payload, null, 2);
}
if (config.targetApi) {
document.getElementById('targetMethod').value = config.targetApi.method;
document.getElementById('targetUrl').value = config.targetApi.url;
document.getElementById('targetHeaders').value = JSON.stringify(config.targetApi.headers, null, 2);
document.getElementById('targetPayload').value = JSON.stringify(config.targetApi.payloadTemplate, null, 2);
}
// 设置映射配置
if (config.mappings) {
this.mappings = config.mappings;
const mappingElement = document.getElementById('mappingContent') || document.getElementById('mappingsTextarea') || document.querySelector('textarea[id^="mapping"]');
if (mappingElement) {
mappingElement.value = JSON.stringify(this.mappings, null, 2);
} else {
console.warn('未找到映射配置输入框元素');
// 创建新的映射配置输入框
const newTextarea = document.createElement('textarea');
newTextarea.id = 'mappingContent';
newTextarea.rows = 10;
newTextarea.cols = 80;
newTextarea.value = JSON.stringify(this.mappings, null, 2);
document.body.appendChild(newTextarea);
}
}
alert(`成功从文件 ${file.name} 加载所有配置`);
} catch (error) {
alert(`解析配置文件失败: ${error.message}`);
}
};
reader.onerror = () => {
alert(`读取文件 ${file.name} 时发生错误`);
};
reader.readAsText(file);
} catch (error) {
alert(`加载配置文件失败: ${error.message}`);
}
}
// 保存全部配置
async saveAllConfig() {
try {
// 验证JSON格式
const validateJSON = (jsonString) => {
try {
JSON.parse(jsonString);
return true;
} catch (e) {
return false;
}
};
// 获取并验证所有表单数据
const sourceHeaders = document.getElementById('sourceHeaders').value;
const sourcePayload = document.getElementById('sourcePayload').value;
const targetHeaders = document.getElementById('targetHeaders').value;
const targetPayload = document.getElementById('targetPayload').value;
const mappingContent = document.getElementById('mappingContent').value;
if (!validateJSON(sourceHeaders) || !validateJSON(sourcePayload) ||
!validateJSON(targetHeaders) || !validateJSON(targetPayload) ||
!validateJSON(mappingContent)) {
throw new Error('请检查JSON格式是否正确');
}
// 合并所有配置
const config = {
sourceApi: {
method: document.getElementById('sourceMethod').value,
url: document.getElementById('sourceUrl').value,
headers: JSON.parse(sourceHeaders),
payload: JSON.parse(sourcePayload)
},
targetApi: {
method: document.getElementById('targetMethod').value,
url: document.getElementById('targetUrl').value,
headers: JSON.parse(targetHeaders),
payloadTemplate: JSON.parse(targetPayload)
},
mappings: JSON.parse(mappingContent)
};
// 保存配置
const blob = new Blob([JSON.stringify(config, null, 2)], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'dhconfig.json';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
alert('所有配置已保存到本地文件dhconfig.json');
} catch (error) {
console.error('保存配置时出错:', error);
alert(`保存配置时出错: ${error.message}`);
}
}
// 初始化事件监听
initEventListeners() {
// 测试源端API连接
document.getElementById('testSourceApi').addEventListener('click', () => {
this.testSourceApi();
});
// 测试目标端API连接
document.getElementById('testTargetApi').addEventListener('click', () => {
this.testTargetApi();
});
// 开始搬运数据
document.getElementById('startTransfer').addEventListener('click', () => {
this.startTransfer();
});
// 定时搬运数据
document.getElementById('scheduleTransfer').addEventListener('click', () => {
this.scheduleTransfer();
});
// 保存配置
document.getElementById('saveAllConfig').addEventListener('click', () => {
this.saveAllConfig();
});
}
// 通用API调用方法
async callApi(url, options) {
try {
const response = await fetch(url, options);
if (!response.ok) {
throw new Error(`HTTP错误! 状态码: ${response.status}`);
}
// 检查响应内容类型是否为JSON
const contentType = response.headers.get('content-type');
if (contentType && contentType.includes('application/json')) {
const data = await response.json();
// 验证返回数据是否为对象
if (typeof data !== 'object' || data === null) {
throw new Error('返回数据必须是JSON对象');
}
return data;
} else {
// 如果不是JSON格式,返回原始文本
return await response.text();
}
} catch (error) {
console.error('API调用失败:', error);
throw error; // 重新抛出错误以便外部捕获
}
}
}
// 初始化应用
window.addEventListener('DOMContentLoaded', () => {
new DataHauler();
});
2.4 dhconfig.json
配置文件
{
"sourceApi": {
"method": "GET",
"url": "http://127.0.0.1:5217/rest/data_type",
"headers": {},
"payload": {}
},
"targetApi": {
"method": "POST",
"url": "http://127.0.0.1:5217/rest/data_type2 ",
"headers": {},
"payloadTemplate": {}
},
"mappings": {
"P_ID2": "data.rows[1].P_ID",
"S_NAME2": "data.rows[1].S_NAME",
"N_AGE2": "data.rows[1].N_AGE"
}
}
3 实操演练
3.1 源端 API GET 数据
首先配置源端 API保证能 GET 到数据,配置好API的URL地址,点【源端测试连接】,源端响应数据应该能看到数据才行。比如如下截图:
数据库表的原始数据如下截图:
3.2 目标端 API POST 数据
配置目标端 API 地址,请求负载,点【目标端测试连接】,目标端有响应数据显示。比如如下截图:
数据库验证时候 POST 成功:
3.3 配置数据映射关系 JSON
- 源数据
{
"data": {
"rows": [
{
"DATE_T": "2025-04-01T09:01:40+08:00",
"N_AGE": 55,
"P_ID": -300,
"S_DATE": "2025-04-01",
"S_NAME": "5217"
},
{
"DATE_T": "2025-04-01T09:01:40+08:00",
"N_AGE": 17,
"P_ID": 1,
"S_DATE": "2025-04-01",
"S_NAME": "blma"
},
{
"DATE_T": "2025-04-01T09:01:40+08:00",
"N_AGE": 52,
"P_ID": 2,
"S_DATE": "2025-04-01",
"S_NAME": "白龙马"
}
]
},
"msg": "",
"status": 0,
"total": 3
}
- 目标数据负载
{
"P_ID2": 222,
"S_NAME2": "blmA",
"N_AGE2": 56
}
- 数据映射关系定义
{
"P_ID2": "data.rows[0].P_ID",
"S_NAME2": "data.rows[0].S_NAME",
"N_AGE2": "data.rows[0].N_AGE"
}
源数据有5个字段,只需要3个字段,只映射3字段即可。
3.4 开始搬运
万事俱备,见证奇迹:点【开始搬运】按钮执行数据搬运。
控制台会有搬运日子输出。检查数据库是否搬运成功:
OK 搬运成功了。
3.5 定时搬运
设置2分钟定时搬运,倒计时开始,倒计时结束成功搬运。
定时设置成功会先执行一次搬运。然后按设定时间定时搬运。良辰吉时已到,检查一下数据库记录。
时间间隔 2:01,
OK!
本文完