feat: 自动提交 - 周一 2025/09/22 11:24:32.93
This commit is contained in:
@@ -4444,6 +4444,18 @@ class FeishuSyncManager {
|
||||
}
|
||||
}
|
||||
|
||||
// 打开字段映射管理页面
|
||||
openFieldMapping() {
|
||||
const section = document.getElementById('fieldMappingSection');
|
||||
if (section.style.display === 'none') {
|
||||
section.style.display = 'block';
|
||||
// 自动加载映射状态
|
||||
this.loadMappingStatus();
|
||||
} else {
|
||||
section.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
async previewFeishuData() {
|
||||
try {
|
||||
this.showNotification('正在获取飞书数据预览...', 'info');
|
||||
@@ -4653,6 +4665,242 @@ class FeishuSyncManager {
|
||||
}
|
||||
}
|
||||
|
||||
// 字段映射管理方法
|
||||
async discoverFields() {
|
||||
try {
|
||||
this.showNotification('正在发现字段...', 'info');
|
||||
|
||||
const response = await fetch('/api/feishu-sync/field-mapping/discover', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ limit: 5 })
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
this.displayDiscoveryResults(data.discovery_report);
|
||||
this.showNotification('字段发现完成', 'success');
|
||||
} else {
|
||||
this.showNotification('字段发现失败: ' + data.error, 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
this.showNotification('字段发现失败: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
displayDiscoveryResults(report) {
|
||||
const container = document.getElementById('fieldMappingContent');
|
||||
let html = '';
|
||||
|
||||
// 已映射字段
|
||||
if (report.mapped_fields && Object.keys(report.mapped_fields).length > 0) {
|
||||
html += '<div class="mb-3"><h6 class="text-success"><i class="fas fa-check-circle"></i> 已映射字段</h6>';
|
||||
for (const [feishuField, localField] of Object.entries(report.mapped_fields)) {
|
||||
html += `<div class="alert alert-success py-2">
|
||||
<strong>${feishuField}</strong> → <span class="badge bg-success">${localField}</span>
|
||||
</div>`;
|
||||
}
|
||||
html += '</div>';
|
||||
}
|
||||
|
||||
// 未映射字段和建议
|
||||
if (report.unmapped_fields && report.unmapped_fields.length > 0) {
|
||||
html += '<div class="mb-3"><h6 class="text-warning"><i class="fas fa-exclamation-triangle"></i> 未映射字段</h6>';
|
||||
for (const field of report.unmapped_fields) {
|
||||
html += `<div class="alert alert-warning py-2">
|
||||
<strong>${field}</strong>`;
|
||||
|
||||
const suggestions = report.suggested_mappings[field] || [];
|
||||
if (suggestions.length > 0) {
|
||||
html += '<div class="mt-2"><small class="text-muted">建议映射:</small>';
|
||||
suggestions.slice(0, 2).forEach(suggestion => {
|
||||
html += `<div class="mt-1">
|
||||
<span class="badge bg-${suggestion.confidence === 'high' ? 'success' : 'warning'}">${suggestion.local_field}</span>
|
||||
<small class="text-muted">(${suggestion.reason})</small>
|
||||
<button class="btn btn-sm btn-outline-primary ms-2" onclick="feishuSync.applySuggestion('${field}', '${suggestion.local_field}')">应用</button>
|
||||
</div>`;
|
||||
});
|
||||
html += '</div>';
|
||||
}
|
||||
|
||||
html += '</div>';
|
||||
}
|
||||
html += '</div>';
|
||||
}
|
||||
|
||||
container.innerHTML = html;
|
||||
}
|
||||
|
||||
async applySuggestion(feishuField, localField) {
|
||||
if (confirm(`确定要将 "${feishuField}" 映射到 "${localField}" 吗?`)) {
|
||||
try {
|
||||
const response = await fetch('/api/feishu-sync/field-mapping/add', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
feishu_field: feishuField,
|
||||
local_field: localField,
|
||||
priority: 3
|
||||
})
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
this.showNotification('映射添加成功!', 'success');
|
||||
this.discoverFields(); // 重新发现字段
|
||||
} else {
|
||||
this.showNotification('添加映射失败: ' + data.error, 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
this.showNotification('请求失败: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async loadMappingStatus() {
|
||||
try {
|
||||
const response = await fetch('/api/feishu-sync/field-mapping/status');
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
this.displayMappingStatus(data.status);
|
||||
} else {
|
||||
this.showNotification('获取映射状态失败: ' + data.error, 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
this.showNotification('请求失败: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
displayMappingStatus(status) {
|
||||
const container = document.getElementById('fieldMappingContent');
|
||||
let html = '';
|
||||
|
||||
html += `<div class="row mb-3">
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title text-primary">${status.total_mappings}</h5>
|
||||
<p class="card-text">直接映射</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title text-info">${status.total_aliases}</h5>
|
||||
<p class="card-text">别名映射</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title text-warning">${status.total_patterns}</h5>
|
||||
<p class="card-text">模式匹配</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title ${status.auto_mapping_enabled ? 'text-success' : 'text-danger'}">
|
||||
${status.auto_mapping_enabled ? '启用' : '禁用'}
|
||||
</h5>
|
||||
<p class="card-text">自动映射</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
// 显示当前映射
|
||||
if (status.field_mapping && Object.keys(status.field_mapping).length > 0) {
|
||||
html += '<h6>当前字段映射:</h6><div class="row">';
|
||||
for (const [feishuField, localField] of Object.entries(status.field_mapping)) {
|
||||
html += `<div class="col-md-6 mb-2">
|
||||
<div class="alert alert-info py-2">
|
||||
<strong>${feishuField}</strong> → <span class="badge bg-primary">${localField}</span>
|
||||
<button class="btn btn-sm btn-outline-danger float-end" onclick="feishuSync.removeMapping('${feishuField}')">删除</button>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
html += '</div>';
|
||||
}
|
||||
|
||||
container.innerHTML = html;
|
||||
}
|
||||
|
||||
async removeMapping(feishuField) {
|
||||
if (confirm(`确定要删除映射 "${feishuField}" 吗?`)) {
|
||||
try {
|
||||
const response = await fetch('/api/feishu-sync/field-mapping/remove', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
feishu_field: feishuField
|
||||
})
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
this.showNotification('映射删除成功!', 'success');
|
||||
this.loadMappingStatus(); // 刷新状态
|
||||
} else {
|
||||
this.showNotification('删除映射失败: ' + data.error, 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
this.showNotification('请求失败: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
showAddMappingModal() {
|
||||
// 简单的添加映射功能
|
||||
const feishuField = prompt('请输入飞书字段名:');
|
||||
if (!feishuField) return;
|
||||
|
||||
const localField = prompt('请输入本地字段名 (如: order_id, description, category):');
|
||||
if (!localField) return;
|
||||
|
||||
this.addFieldMapping(feishuField, localField);
|
||||
}
|
||||
|
||||
async addFieldMapping(feishuField, localField) {
|
||||
try {
|
||||
const response = await fetch('/api/feishu-sync/field-mapping/add', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
feishu_field: feishuField,
|
||||
local_field: localField,
|
||||
priority: 3
|
||||
})
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
this.showNotification('映射添加成功!', 'success');
|
||||
this.loadMappingStatus(); // 刷新状态
|
||||
} else {
|
||||
this.showNotification('添加映射失败: ' + data.error, 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
this.showNotification('请求失败: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
showNotification(message, type = 'info') {
|
||||
const container = document.getElementById('notificationContainer');
|
||||
const alert = document.createElement('div');
|
||||
|
||||
Reference in New Issue
Block a user