Kinlink代理示例

API代理系统概览

构建强大的后端集成能力,实现数据同步和业务流程自动化

此示例演示如何使用kinlink proxy API与外部系统集成,实现数据的双向同步实时处理业务自动化。通过代理服务,可以安全地与企业内部系统、第三方API和云服务进行通信。

API代理核心功能

  • 🔗 外部集成:与第三方API和内部系统无缝对接
  • 🔐 安全通信:加密传输和身份验证机制
  • 🔄 数据同步:实时或批量数据同步处理
  • 高性能:异步处理和请求优化
  • 📊 监控日志:完整的请求追踪和错误处理
  • 🛡️ 错误恢复:自动重试和故障转移机制

关键功能

  • HTTP请求代理和转发
  • 数据格式转换和映射
  • 认证和权限管理
  • 错误处理和重试机制

代码示例

/**
* 示例14: Kinlink代理集成
* 功能:使用代理API与外部系统集成,实现数据同步和业务自动化
*/
(function () {
// 代理配置
const PROXY_CONFIG = {
  baseUrl: 'https://api.example.com',
  endpoints: {
    users: '/api/users',
    orders: '/api/orders',
    notifications: '/api/notifications',
    validation: '/api/validate'
  },
  timeout: 10000,
  retryCount: 3,
  retryDelay: 1000
};

// 认证配置
const AUTH_CONFIG = {
  type: 'bearer', // 或 'basic', 'api-key'
  token: null,
  refreshUrl: '/api/auth/refresh'
};

// 请求队列和状态管理
let requestQueue = [];
let isProcessingQueue = false;
let authToken = null;

kinlink.events.on(kinlink.FormEvents.FORM_LOADED, () => {
  try {
    console.log('初始化Kinlink代理系统...');
    
    // 创建代理管理面板
    createProxyDashboard();
    
    // 初始化认证
    initializeAuth();
    
    // 设置表单事件监听
    setupFormEventListeners();
    
    // 启动定时任务
    startPeriodicTasks();
    
    console.log('Kinlink代理系统初始化完成');
    
  } catch (error) {
    console.error('代理系统初始化失败:', error);
  }
});

// 创建代理管理面板
function createProxyDashboard() {
  const dashboardHTML = `
    <div id="proxyDashboard" style="
      background: linear-gradient(135deg, #8e44ad 0%, #3498db 100%);
      padding: 25px;
      margin: 20px 0;
      border-radius: 15px;
      color: white;
      box-shadow: 0 6px 25px rgba(142, 68, 173, 0.3);
    ">
      <div style="text-align: center; margin-bottom: 25px;">
        <h2 style="margin: 0 0 10px 0; font-size: 26px; font-weight: 700;">
          🔗 Kinlink代理系统
        </h2>
        <div style="font-size: 15px; opacity: 0.95;">
          实时监控外部API集成状态和数据同步
        </div>
      </div>
      
      <div id="proxyStats" style="
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
        gap: 15px;
        margin-bottom: 20px;
      ">
        <div style="background: rgba(255,255,255,0.15); padding: 15px; border-radius: 10px; text-align: center;">
          <div style="font-size: 24px; font-weight: 600; margin-bottom: 5px;" id="totalRequests">0</div>
          <div style="font-size: 13px; opacity: 0.9;">总请求数</div>
        </div>
        <div style="background: rgba(255,255,255,0.15); padding: 15px; border-radius: 10px; text-align: center;">
          <div style="font-size: 24px; font-weight: 600; margin-bottom: 5px;" id="successRate">100%</div>
          <div style="font-size: 13px; opacity: 0.9;">成功率</div>
        </div>
        <div style="background: rgba(255,255,255,0.15); padding: 15px; border-radius: 10px; text-align: center;">
          <div style="font-size: 24px; font-weight: 600; margin-bottom: 5px;" id="queueLength">0</div>
          <div style="font-size: 13px; opacity: 0.9;">队列长度</div>
        </div>
        <div style="background: rgba(255,255,255,0.15); padding: 15px; border-radius: 10px; text-align: center;">
          <div style="font-size: 24px; font-weight: 600; margin-bottom: 5px;" id="connectionStatus">连接中</div>
          <div style="font-size: 13px; opacity: 0.9;">连接状态</div>
    </div>
  </div>

      <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px; margin-bottom: 20px;">
        <button id="testConnection" style="padding: 12px; background: rgba(255,255,255,0.2); color: white; border: 2px solid rgba(255,255,255,0.3); border-radius: 8px; cursor: pointer; transition: all 0.3s ease; font-weight: 500;">
          🔍 测试连接
        </button>
        <button id="syncData" style="padding: 12px; background: rgba(255,255,255,0.2); color: white; border: 2px solid rgba(255,255,255,0.3); border-radius: 8px; cursor: pointer; transition: all 0.3s ease; font-weight: 500;">
          🔄 同步数据
        </button>
        <button id="clearQueue" style="padding: 12px; background: rgba(255,255,255,0.2); color: white; border: 2px solid rgba(255,255,255,0.3); border-radius: 8px; cursor: pointer; transition: all 0.3s ease; font-weight: 500;">
          🗑️ 清空队列
        </button>
        <button id="showLogs" style="padding: 12px; background: rgba(255,255,255,0.2); color: white; border: 2px solid rgba(255,255,255,0.3); border-radius: 8px; cursor: pointer; transition: all 0.3s ease; font-weight: 500;">
          📋 查看日志
        </button>
      </div>
      
      <div id="requestLog" style="
        background: rgba(0,0,0,0.2);
        padding: 15px;
        border-radius: 8px;
        max-height: 200px;
        overflow-y: auto;
        font-size: 12px;
        font-family: monospace;
        line-height: 1.4;
      ">
        <div>系统就绪,等待API请求...</div>
      </div>
    </div>
  `;

  // 插入面板到表单顶部
  const formElement = document.querySelector('.ant-form') || document.body;
  const dashboardElement = document.createElement('div');
  dashboardElement.innerHTML = dashboardHTML;
  formElement.insertBefore(dashboardElement, formElement.firstChild);

  // 绑定面板事件
  bindDashboardEvents();
}

// 绑定面板事件
function bindDashboardEvents() {
  const dashboard = document.getElementById('proxyDashboard');
  if (!dashboard) return;

  dashboard.addEventListener('click', async (e) => {
    const target = e.target;
    
    if (target.id === 'testConnection') {
      await testApiConnection();
    } else if (target.id === 'syncData') {
      await performDataSync();
    } else if (target.id === 'clearQueue') {
      clearRequestQueue();
    } else if (target.id === 'showLogs') {
      showDetailedLogs();
    }
  });
}

// 初始化认证
async function initializeAuth() {
  try {
    // 尝试从本地存储获取令牌
    const storedToken = localStorage.getItem('kinlink_proxy_token');
    if (storedToken) {
      authToken = storedToken;
      AUTH_CONFIG.token = storedToken;
    }

    // 验证令牌有效性
    if (authToken) {
      const isValid = await validateToken(authToken);
      if (!isValid) {
        await refreshAuthToken();
      }
    } else {
      await requestNewToken();
    }

    logMessage('认证初始化完成', 'success');
  } catch (error) {
    logMessage(`认证失败: ${error.message}`, 'error');
  }
}

// 验证令牌
async function validateToken(token) {
  try {
    const response = await makeProxyRequest('/api/auth/validate', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json'
      }
    });

    return response.status === 200;
  } catch (error) {
    return false;
  }
}

// 刷新认证令牌
async function refreshAuthToken() {
  try {
    const response = await makeProxyRequest(AUTH_CONFIG.refreshUrl, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${authToken}`,
        'Content-Type': 'application/json'
      }
    });

    if (response.ok) {
      const data = await response.json();
      authToken = data.token;
      AUTH_CONFIG.token = authToken;
      localStorage.setItem('kinlink_proxy_token', authToken);
      logMessage('令牌刷新成功', 'success');
    } else {
      throw new Error('令牌刷新失败');
    }
  } catch (error) {
    logMessage(`令牌刷新失败: ${error.message}`, 'error');
    await requestNewToken();
  }
}

// 请求新令牌
async function requestNewToken() {
  // 这里应该实现获取新令牌的逻辑
  // 可能需要重新登录或使用其他认证方式
  logMessage('需要重新认证', 'warning');
}

// 设置表单事件监听
function setupFormEventListeners() {
  // 监听表单提交前事件
  kinlink.events.on(kinlink.FormEvents.BEFORE_SUBMIT, handleBeforeSubmit);
      
  // 监听表单提交后事件
  kinlink.events.on(kinlink.FormEvents.AFTER_SUBMIT, handleAfterSubmit);
  
  // 监听字段值变化
  kinlink.events.on(kinlink.FormEvents.FIELD_VALUE_CHANGED, handleFieldChange);
}

// 处理提交前事件
async function handleBeforeSubmit(data) {
  try {
    logMessage('开始表单验证...', 'info');
    
    // 调用外部验证API
    const validationResult = await validateFormData(data.values);
    
    if (!validationResult.valid) {
      kinlink.formApi.showMessage('error', `验证失败: ${validationResult.message}`, 5);
      return false; // 阻止提交
    }
    
    logMessage('表单验证通过', 'success');
    return true;
  } catch (error) {
    logMessage(`验证过程出错: ${error.message}`, 'error');
    kinlink.formApi.showMessage('error', '验证服务暂时不可用,请稍后重试', 3);
    return false;
  }
        }
        
// 处理提交后事件
async function handleAfterSubmit(data) {
  if (data.success) {
    try {
      logMessage('开始数据同步...', 'info');
      
      // 同步到外部系统
      await syncToExternalSystems(data.submittedData);
      
      // 发送通知
      await sendNotifications(data.submittedData);
      
      logMessage('数据同步完成', 'success');
    } catch (error) {
      logMessage(`同步失败: ${error.message}`, 'error');
    }
  }
}

// 处理字段变化
async function handleFieldChange(data) {
  const { fieldCode, value } = data;
  
  // 对特定字段进行实时验证
  if (fieldCode === '文字列__1行__3') { // 邮箱字段
    await validateEmailField(value);
  }
  
  // 更新外部系统的草稿
  queueRequest({
    type: 'UPDATE_DRAFT',
    fieldCode,
    value,
    timestamp: new Date().toISOString()
  });
}

// 执行代理请求
async function makeProxyRequest(endpoint, options = {}) {
  const url = `${PROXY_CONFIG.baseUrl}${endpoint}`;
  
  const requestOptions = {
    timeout: PROXY_CONFIG.timeout,
    ...options,
    headers: {
      'Content-Type': 'application/json',
      'Authorization': authToken ? `Bearer ${authToken}` : undefined,
      ...options.headers
    }
  };

  try {
    // 使用kinlink的代理功能
    const response = await kinlink.proxy.request(url, requestOptions);
    
    updateStats('success');
    logMessage(`请求成功: ${endpoint}`, 'success');
    
    return response;
  } catch (error) {
    updateStats('error');
    logMessage(`请求失败: ${endpoint} - ${error.message}`, 'error');
    
    // 实现重试逻辑
    if (shouldRetry(error)) {
      return await retryRequest(endpoint, options);
    }
    
    throw error;
  }
}

// 重试请求
async function retryRequest(endpoint, options, attempt = 1) {
  if (attempt > PROXY_CONFIG.retryCount) {
    throw new Error(`请求失败,已达到最大重试次数: ${endpoint}`);
  }

  logMessage(`重试请求 (${attempt}/${PROXY_CONFIG.retryCount}): ${endpoint}`, 'warning');
  
  // 等待重试延迟
  await new Promise(resolve => setTimeout(resolve, PROXY_CONFIG.retryDelay * attempt));
  
  try {
    return await makeProxyRequest(endpoint, options);
  } catch (error) {
    return await retryRequest(endpoint, options, attempt + 1);
  }
}

// 判断是否应该重试
function shouldRetry(error) {
  const retryableErrors = ['NETWORK_ERROR', 'TIMEOUT', 'SERVER_ERROR'];
  return retryableErrors.some(errorType => error.message.includes(errorType));
}

// 验证表单数据
async function validateFormData(formData) {
  try {
    const response = await makeProxyRequest(PROXY_CONFIG.endpoints.validation, {
      method: 'POST',
      body: JSON.stringify(formData)
    });

    if (response.ok) {
      const result = await response.json();
      return result;
          } else {
      return { valid: false, message: '验证服务返回错误' };
    }
  } catch (error) {
    return { valid: false, message: error.message };
  }
}

// 验证邮箱字段
async function validateEmailField(email) {
  if (!email || !email.includes('@')) return;

  try {
    const response = await makeProxyRequest('/api/validate/email', {
      method: 'POST',
      body: JSON.stringify({ email })
    });

    if (response.ok) {
      const result = await response.json();
      if (!result.valid) {
        kinlink.formApi.showMessage('warning', result.message, 3);
      }
          }
        } catch (error) {
    console.warn('邮箱验证失败:', error);
  }
}

// 同步到外部系统
async function syncToExternalSystems(data) {
  const syncTasks = [
    syncToUserSystem(data),
    syncToOrderSystem(data),
    updateAnalytics(data)
  ];

  const results = await Promise.allSettled(syncTasks);
  
  results.forEach((result, index) => {
    if (result.status === 'rejected') {
      logMessage(`同步任务 ${index + 1} 失败: ${result.reason.message}`, 'error');
    }
  });
}

// 同步到用户系统
async function syncToUserSystem(data) {
  return await makeProxyRequest(PROXY_CONFIG.endpoints.users, {
    method: 'POST',
    body: JSON.stringify({
      action: 'create_or_update',
      userData: extractUserData(data)
    })
  });
}

// 同步到订单系统
async function syncToOrderSystem(data) {
  return await makeProxyRequest(PROXY_CONFIG.endpoints.orders, {
    method: 'POST',
    body: JSON.stringify({
      action: 'create',
      orderData: extractOrderData(data)
    })
  });
}

// 更新分析数据
async function updateAnalytics(data) {
  return await makeProxyRequest('/api/analytics/events', {
    method: 'POST',
    body: JSON.stringify({
      event: 'form_submission',
      timestamp: new Date().toISOString(),
      data: data
    })
  });
}

// 发送通知
async function sendNotifications(data) {
  const notifications = [
    {
      type: 'email',
      to: data['文字列__1行__3'], // 邮箱字段
      template: 'submission_confirmation',
      data: data
    },
    {
      type: 'webhook',
      url: 'https://hooks.example.com/form-submission',
      data: data
    }
  ];

  for (const notification of notifications) {
    try {
      await makeProxyRequest(PROXY_CONFIG.endpoints.notifications, {
        method: 'POST',
        body: JSON.stringify(notification)
      });
      logMessage(`通知发送成功: ${notification.type}`, 'success');
    } catch (error) {
      logMessage(`通知发送失败: ${notification.type} - ${error.message}`, 'error');
    }
  }
}

// 提取用户数据
function extractUserData(formData) {
  return {
    name: formData['文字列__1行__0'],
    email: formData['文字列__1行__3'],
    phone: formData['文字列__1行__2'],
    company: formData['单行文本框_10']
  };
}

// 提取订单数据
function extractOrderData(formData) {
  return {
    customerEmail: formData['文字列__1行__3'],
    orderDate: new Date().toISOString(),
    items: [], // 根据表单数据解析
    total: 0 // 根据表单数据计算
  };
}

// 队列管理
function queueRequest(request) {
  requestQueue.push({
    ...request,
    id: Date.now(),
    status: 'pending'
  });
  
  updateQueueDisplay();
  
  if (!isProcessingQueue) {
    processQueue();
  }
}

// 处理请求队列
async function processQueue() {
  if (isProcessingQueue || requestQueue.length === 0) return;
  
  isProcessingQueue = true;
  
  while (requestQueue.length > 0) {
    const request = requestQueue.shift();
    
    try {
      await processQueuedRequest(request);
      logMessage(`队列请求处理成功: ${request.type}`, 'success');
    } catch (error) {
      logMessage(`队列请求处理失败: ${request.type} - ${error.message}`, 'error');
    }
    
    updateQueueDisplay();
  }
  
  isProcessingQueue = false;
}

// 处理队列中的请求
async function processQueuedRequest(request) {
  switch (request.type) {
    case 'UPDATE_DRAFT':
      return await updateDraft(request);
    case 'SYNC_DATA':
      return await syncSingleData(request);
    default:
      throw new Error(`未知请求类型: ${request.type}`);
  }
}

// 更新草稿
async function updateDraft(request) {
  return await makeProxyRequest('/api/drafts/update', {
    method: 'PUT',
    body: JSON.stringify({
      fieldCode: request.fieldCode,
      value: request.value,
      timestamp: request.timestamp
    })
  });
}

// 测试API连接
async function testApiConnection() {
  try {
    logMessage('测试API连接...', 'info');
    
    const response = await makeProxyRequest('/api/health', {
      method: 'GET'
    });

    if (response.ok) {
      logMessage('API连接正常', 'success');
      kinlink.formApi.showMessage('success', 'API连接测试成功', 2);
      updateConnectionStatus('connected');
    } else {
      throw new Error('API返回错误状态');
    }
  } catch (error) {
    logMessage(`API连接失败: ${error.message}`, 'error');
    kinlink.formApi.showMessage('error', 'API连接测试失败', 2);
    updateConnectionStatus('disconnected');
  }
}

// 执行数据同步
async function performDataSync() {
  try {
    logMessage('开始手动数据同步...', 'info');
    
    const formData = kinlink.formApi.getAllFieldValues();
    await syncToExternalSystems(formData);
    
    logMessage('手动数据同步完成', 'success');
    kinlink.formApi.showMessage('success', '数据同步成功', 2);
  } catch (error) {
    logMessage(`数据同步失败: ${error.message}`, 'error');
    kinlink.formApi.showMessage('error', '数据同步失败', 2);
  }
}

// 清空请求队列
function clearRequestQueue() {
  requestQueue = [];
  updateQueueDisplay();
  logMessage('请求队列已清空', 'info');
  kinlink.formApi.showMessage('info', '队列已清空', 2);
  }

// 显示详细日志
function showDetailedLogs() {
  const logs = document.getElementById('requestLog').innerHTML;
  const newWindow = window.open('', '_blank', 'width=800,height=600');
  newWindow.document.write(`
    <html>
      <head><title>API请求日志</title></head>
      <body style="font-family: monospace; padding: 20px;">
        <h1>API请求详细日志</h1>
        <div style="background: #f5f5f5; padding: 15px; border-radius: 5px;">
          ${logs}
        </div>
      </body>
    </html>
  `);
}

// 记录日志消息
function logMessage(message, type = 'info') {
  const timestamp = new Date().toLocaleTimeString();
  const logElement = document.getElementById('requestLog');
  
  if (logElement) {
    const colors = {
      info: '#3498db',
      success: '#27ae60',
      warning: '#f39c12',
      error: '#e74c3c'
    };
    
    const newLog = document.createElement('div');
    newLog.style.color = colors[type] || colors.info;
    newLog.innerHTML = `[${timestamp}] ${message}`;
    
    logElement.appendChild(newLog);
    
    // 保持最多50条日志
    while (logElement.children.length > 50) {
      logElement.removeChild(logElement.firstChild);
    }
    
    // 滚动到底部
    logElement.scrollTop = logElement.scrollHeight;
  }
}

// 更新统计数据
let totalRequests = 0;
let successfulRequests = 0;

function updateStats(type) {
  totalRequests++;
  if (type === 'success') {
    successfulRequests++;
  }
  
  const successRate = totalRequests > 0 ? Math.round((successfulRequests / totalRequests) * 100) : 100;
  
  document.getElementById('totalRequests').textContent = totalRequests;
  document.getElementById('successRate').textContent = `${successRate}%`;
}

// 更新队列显示
function updateQueueDisplay() {
  document.getElementById('queueLength').textContent = requestQueue.length;
}

// 更新连接状态
function updateConnectionStatus(status) {
  const statusElement = document.getElementById('connectionStatus');
  const statusTexts = {
    connected: '已连接',
    disconnected: '未连接',
    connecting: '连接中'
  };
  
  statusElement.textContent = statusTexts[status] || status;
}

// 启动定时任务
function startPeriodicTasks() {
  // 每30秒检查连接状态
  setInterval(async () => {
    await testApiConnection();
  }, 30000);
  
  // 每10秒处理队列
  setInterval(() => {
    if (!isProcessingQueue && requestQueue.length > 0) {
      processQueue();
    }
  }, 10000);
}
})();

使用说明

要使用此功能,只需将代码复制到您的kinlink自定义JavaScript中。请根据您的实际API配置修改代理地址、认证信息和端点路径。

完整代码请下载查看:

14-kinlink proxy.js

注意事项

使用代理功能需要确保目标API支持CORS或配置了适当的代理服务器。认证信息应安全存储,避免在前端代码中暴露敏感数据。

API参考

此示例使用了以下kinlink API:
  • kinlink.events.on(eventName, callback) - 注册事件监听器

  • kinlink.FormEvents.FORM_LOADED - 表单加载完成事件

  • kinlink.FormEvents.BEFORE_SUBMIT - 表单提交前事件

  • kinlink.FormEvents.AFTER_SUBMIT - 表单提交后事件

  • kinlink.FormEvents.FIELD_VALUE_CHANGED - 字段值变化事件

  • kinlink.proxy.request(url, options) - 执行代理HTTP请求

  • kinlink.formApi.getAllFieldValues() - 获取所有字段值

  • kinlink.formApi.showMessage(type, message, duration) - 显示消息提示