2025-04-30 14:50:27 +08:00
|
|
|
import './interface-config/toolbar.js';
|
|
|
|
import './interface-config/data-table.js';
|
|
|
|
import './interface-config/variable-form.js';
|
2025-05-07 13:46:48 +08:00
|
|
|
import './interface-config/import-dialog.js';
|
2025-04-30 14:50:27 +08:00
|
|
|
|
2025-04-28 12:25:20 +08:00
|
|
|
class InterfaceConfig extends HTMLElement {
|
|
|
|
constructor() {
|
|
|
|
super();
|
|
|
|
this.attachShadow({ mode: 'open' });
|
2025-04-30 14:50:27 +08:00
|
|
|
this.data = [];
|
2025-05-16 10:26:07 +08:00
|
|
|
this.planes = []; // 存储构型列表
|
2025-05-07 13:46:48 +08:00
|
|
|
this.atas = []; // 存储ATA章节列表
|
2025-04-28 12:25:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
connectedCallback() {
|
|
|
|
this.render();
|
|
|
|
this.addEventListeners();
|
2025-05-07 13:46:48 +08:00
|
|
|
this.loadData();
|
2025-04-28 12:25:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
addEventListeners() {
|
2025-04-30 14:50:27 +08:00
|
|
|
const toolbar = this.shadowRoot.querySelector('interface-toolbar');
|
|
|
|
const dataTable = this.shadowRoot.querySelector('interface-data-table');
|
|
|
|
const variableForm = this.shadowRoot.querySelector('variable-form');
|
2025-05-07 13:46:48 +08:00
|
|
|
const importDialog = this.shadowRoot.querySelector('import-dialog');
|
2025-04-30 14:50:27 +08:00
|
|
|
|
|
|
|
// 添加变量事件
|
|
|
|
toolbar.addEventListener('add-variable', () => {
|
|
|
|
variableForm.setMode('add');
|
|
|
|
variableForm.show();
|
2025-04-28 12:25:20 +08:00
|
|
|
});
|
|
|
|
|
2025-04-30 14:50:27 +08:00
|
|
|
// 删除变量事件
|
|
|
|
toolbar.addEventListener('delete-variable', async () => {
|
|
|
|
const selectedRows = dataTable.getSelectedRows();
|
|
|
|
if (selectedRows.length === 0) {
|
|
|
|
alert('请选择要删除的接口');
|
2025-04-28 12:25:20 +08:00
|
|
|
return;
|
|
|
|
}
|
2025-05-07 13:46:48 +08:00
|
|
|
|
2025-04-30 14:50:27 +08:00
|
|
|
if (!confirm(`确定要删除选中的 ${selectedRows.length} 个接口吗?`)) {
|
2025-05-16 10:26:07 +08:00
|
|
|
return;
|
|
|
|
}
|
2025-05-07 13:46:48 +08:00
|
|
|
|
2025-05-16 10:26:07 +08:00
|
|
|
try {
|
|
|
|
const savedSelection = localStorage.getItem('xnsim-selection');
|
|
|
|
if (!savedSelection) {
|
|
|
|
throw new Error('请先选择构型');
|
|
|
|
}
|
|
|
|
const selection = JSON.parse(savedSelection);
|
|
|
|
if (!selection.configurationId) {
|
|
|
|
throw new Error('请先选择构型');
|
|
|
|
}
|
|
|
|
|
2025-04-30 14:50:27 +08:00
|
|
|
const deletePromises = selectedRows.map(row => {
|
2025-05-16 10:26:07 +08:00
|
|
|
const { InterfaceName } = row;
|
|
|
|
return fetch(`/api/interface/delete?interfaceName=${InterfaceName}&confID=${selection.configurationId}`, {
|
2025-04-30 14:50:27 +08:00
|
|
|
method: 'DELETE'
|
2025-05-16 10:26:07 +08:00
|
|
|
});
|
|
|
|
});
|
2025-05-07 13:46:48 +08:00
|
|
|
|
2025-04-30 14:50:27 +08:00
|
|
|
const results = await Promise.all(deletePromises);
|
|
|
|
const failed = results.some(result => !result.ok);
|
2025-04-28 12:25:20 +08:00
|
|
|
|
2025-04-30 14:50:27 +08:00
|
|
|
if (failed) {
|
|
|
|
throw new Error('删除失败');
|
2025-04-28 12:25:20 +08:00
|
|
|
}
|
2025-04-30 14:50:27 +08:00
|
|
|
|
|
|
|
await this.loadData();
|
|
|
|
alert('删除成功');
|
|
|
|
} catch (error) {
|
|
|
|
console.error('删除接口时出错:', error);
|
2025-05-16 10:26:07 +08:00
|
|
|
alert(error.message || '删除接口失败');
|
2025-04-28 12:25:20 +08:00
|
|
|
}
|
2025-04-30 14:50:27 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
// 导入数据事件
|
2025-05-07 13:46:48 +08:00
|
|
|
toolbar.addEventListener('import-data', async (e) => {
|
|
|
|
const { file, type } = e.detail;
|
|
|
|
if (!file) return;
|
2025-04-30 14:50:27 +08:00
|
|
|
|
2025-05-07 13:46:48 +08:00
|
|
|
const formData = new FormData();
|
|
|
|
formData.append('file', file);
|
|
|
|
formData.append('type', type);
|
2025-04-30 14:50:27 +08:00
|
|
|
|
2025-05-07 13:46:48 +08:00
|
|
|
try {
|
|
|
|
const response = await fetch('/api/icd/import', {
|
|
|
|
method: 'POST',
|
|
|
|
body: formData
|
|
|
|
});
|
2025-04-30 14:50:27 +08:00
|
|
|
|
2025-05-07 13:46:48 +08:00
|
|
|
if (!response.ok) {
|
|
|
|
throw new Error('导入失败');
|
|
|
|
}
|
2025-04-30 14:50:27 +08:00
|
|
|
|
2025-05-07 13:46:48 +08:00
|
|
|
const result = await response.json();
|
|
|
|
if (result.success) {
|
|
|
|
importDialog.show(result.data);
|
|
|
|
} else {
|
|
|
|
throw new Error(result.error || '导入失败');
|
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
console.error('导入数据时出错:', error);
|
|
|
|
alert('导入数据失败: ' + error.message);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// 确认导入事件
|
|
|
|
importDialog.addEventListener('confirm-import', async (e) => {
|
|
|
|
const importData = e.detail;
|
|
|
|
try {
|
2025-05-16 10:26:07 +08:00
|
|
|
const savedSelection = localStorage.getItem('xnsim-selection');
|
|
|
|
if (!savedSelection) {
|
|
|
|
throw new Error('请先选择构型');
|
|
|
|
}
|
|
|
|
const selection = JSON.parse(savedSelection);
|
|
|
|
if (!selection.configurationId) {
|
|
|
|
throw new Error('请先选择构型');
|
|
|
|
}
|
|
|
|
|
|
|
|
// 为每个导入项添加 confID
|
|
|
|
const importDataWithConfID = importData.map(item => ({
|
|
|
|
...item,
|
|
|
|
ConfID: selection.configurationId
|
|
|
|
}));
|
|
|
|
|
|
|
|
console.log('准备导入的数据:', importDataWithConfID);
|
2025-05-07 13:46:48 +08:00
|
|
|
|
|
|
|
const response = await fetch('/api/interface/import', {
|
|
|
|
method: 'POST',
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
},
|
2025-05-16 10:26:07 +08:00
|
|
|
body: JSON.stringify(importDataWithConfID)
|
2025-05-07 13:46:48 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
if (!response.ok) {
|
|
|
|
const errorData = await response.json();
|
|
|
|
throw new Error(errorData.error || '保存导入数据失败');
|
|
|
|
}
|
|
|
|
|
|
|
|
const result = await response.json();
|
|
|
|
if (result.success) {
|
|
|
|
await this.loadData();
|
|
|
|
alert('导入成功');
|
|
|
|
} else {
|
|
|
|
throw new Error(result.error || '保存导入数据失败');
|
2025-04-30 14:50:27 +08:00
|
|
|
}
|
2025-05-07 13:46:48 +08:00
|
|
|
} catch (error) {
|
|
|
|
console.error('保存导入数据时出错:', error);
|
2025-05-16 10:26:07 +08:00
|
|
|
alert(error.message || '保存导入数据失败');
|
2025-05-07 13:46:48 +08:00
|
|
|
}
|
2025-04-30 14:50:27 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
// 表格编辑按钮事件
|
|
|
|
dataTable.addEventListener('edit', (e) => {
|
2025-05-07 13:46:48 +08:00
|
|
|
const variableForm = this.shadowRoot.querySelector('variable-form');
|
|
|
|
if (variableForm) {
|
|
|
|
// 确保在设置编辑数据之前先设置选项
|
2025-05-16 10:26:07 +08:00
|
|
|
variableForm.setOptions(this.planes, this.atas);
|
2025-05-07 13:46:48 +08:00
|
|
|
// 先显示表单,再设置模式和数据
|
2025-04-30 14:50:27 +08:00
|
|
|
variableForm.show();
|
2025-05-07 13:46:48 +08:00
|
|
|
variableForm.setMode('edit', e.detail);
|
2025-04-28 12:25:20 +08:00
|
|
|
}
|
|
|
|
});
|
2025-04-30 14:50:27 +08:00
|
|
|
|
|
|
|
// 表格删除按钮事件
|
|
|
|
dataTable.addEventListener('delete', async (e) => {
|
2025-05-16 10:26:07 +08:00
|
|
|
const { InterfaceName } = e.detail;
|
2025-04-30 14:50:27 +08:00
|
|
|
|
|
|
|
try {
|
2025-05-16 10:26:07 +08:00
|
|
|
const savedSelection = localStorage.getItem('xnsim-selection');
|
|
|
|
if (!savedSelection) {
|
|
|
|
throw new Error('请先选择构型');
|
|
|
|
}
|
|
|
|
const selection = JSON.parse(savedSelection);
|
|
|
|
if (!selection.configurationId) {
|
|
|
|
throw new Error('请先选择构型');
|
|
|
|
}
|
|
|
|
|
|
|
|
const response = await fetch(`/api/interface/delete?interfaceName=${InterfaceName}&confID=${selection.configurationId}`, {
|
2025-04-30 14:50:27 +08:00
|
|
|
method: 'DELETE'
|
|
|
|
});
|
|
|
|
|
|
|
|
if (!response.ok) {
|
|
|
|
throw new Error('删除失败');
|
2025-04-28 12:25:20 +08:00
|
|
|
}
|
2025-04-30 14:50:27 +08:00
|
|
|
|
|
|
|
await this.loadData();
|
|
|
|
alert('删除成功');
|
|
|
|
} catch (error) {
|
|
|
|
console.error('删除接口时出错:', error);
|
2025-05-16 10:26:07 +08:00
|
|
|
alert(error.message || '删除接口失败');
|
2025-04-28 12:25:20 +08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2025-04-30 14:50:27 +08:00
|
|
|
// 表单保存成功事件
|
|
|
|
variableForm.addEventListener('save-success', async (e) => {
|
|
|
|
const interfaceData = e.detail;
|
|
|
|
try {
|
|
|
|
const url = interfaceData.mode === 'add' ? '/api/interface/add' : '/api/interface/update';
|
|
|
|
const method = interfaceData.mode === 'add' ? 'POST' : 'PUT';
|
2025-04-28 12:25:20 +08:00
|
|
|
|
2025-05-07 13:46:48 +08:00
|
|
|
// 如果是编辑模式,需要添加原始数据用于更新
|
|
|
|
const requestData = interfaceData.mode === 'edit' ? {
|
|
|
|
currentData: {
|
|
|
|
SystemName: 'XNSim',
|
2025-05-16 10:26:07 +08:00
|
|
|
PlaneName: interfaceData.PlaneName,
|
2025-05-07 13:46:48 +08:00
|
|
|
ATAName: interfaceData.ATAName,
|
|
|
|
ModelStructName: interfaceData.ModelStructName,
|
|
|
|
InterfaceName: interfaceData.InterfaceName,
|
|
|
|
InterfaceType: interfaceData.InterfaceType,
|
|
|
|
InterfaceOption: interfaceData.InterfaceOption || 1,
|
|
|
|
InterfaceIsArray: interfaceData.InterfaceIsArray,
|
|
|
|
InterfaceArraySize_1: interfaceData.InterfaceArraySize_1,
|
|
|
|
InterfaceArraySize_2: interfaceData.InterfaceArraySize_2,
|
2025-05-16 10:26:07 +08:00
|
|
|
InterfaceNotes: interfaceData.InterfaceNotes,
|
|
|
|
ConfID: interfaceData.ConfID
|
2025-05-07 13:46:48 +08:00
|
|
|
},
|
|
|
|
originalData: {
|
|
|
|
SystemName: 'XNSim',
|
2025-05-16 10:26:07 +08:00
|
|
|
PlaneName: interfaceData.originalPlaneName || interfaceData.PlaneName,
|
2025-05-07 13:46:48 +08:00
|
|
|
ATAName: interfaceData.originalATAName || interfaceData.ATAName,
|
|
|
|
ModelStructName: interfaceData.originalModelStructName || interfaceData.ModelStructName,
|
|
|
|
InterfaceName: interfaceData.originalInterfaceName || interfaceData.InterfaceName
|
|
|
|
}
|
|
|
|
} : {
|
|
|
|
SystemName: 'XNSim',
|
2025-05-16 10:26:07 +08:00
|
|
|
PlaneName: interfaceData.PlaneName,
|
2025-05-07 13:46:48 +08:00
|
|
|
ATAName: interfaceData.ATAName,
|
|
|
|
ModelStructName: interfaceData.ModelStructName,
|
|
|
|
InterfaceName: interfaceData.InterfaceName,
|
|
|
|
InterfaceType: interfaceData.InterfaceType,
|
|
|
|
InterfaceOption: interfaceData.InterfaceOption || 1,
|
|
|
|
InterfaceIsArray: interfaceData.InterfaceIsArray,
|
|
|
|
InterfaceArraySize_1: interfaceData.InterfaceArraySize_1,
|
|
|
|
InterfaceArraySize_2: interfaceData.InterfaceArraySize_2,
|
2025-05-16 10:26:07 +08:00
|
|
|
InterfaceNotes: interfaceData.InterfaceNotes,
|
|
|
|
ConfID: interfaceData.ConfID
|
2025-05-07 13:46:48 +08:00
|
|
|
};
|
|
|
|
|
2025-04-30 14:50:27 +08:00
|
|
|
const response = await fetch(url, {
|
|
|
|
method,
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
},
|
2025-05-07 13:46:48 +08:00
|
|
|
body: JSON.stringify(requestData)
|
2025-04-30 14:50:27 +08:00
|
|
|
});
|
2025-05-07 13:46:48 +08:00
|
|
|
|
|
|
|
const responseText = await response.text();
|
|
|
|
let responseData;
|
|
|
|
try {
|
|
|
|
responseData = JSON.parse(responseText);
|
|
|
|
} catch (e) {
|
|
|
|
throw new Error('服务器响应格式错误');
|
|
|
|
}
|
2025-04-28 12:25:20 +08:00
|
|
|
|
2025-04-30 14:50:27 +08:00
|
|
|
if (!response.ok) {
|
2025-05-07 13:46:48 +08:00
|
|
|
throw new Error(responseData.error || '保存失败');
|
2025-04-30 14:50:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
await this.loadData();
|
|
|
|
alert('保存成功');
|
|
|
|
} catch (error) {
|
|
|
|
console.error('保存接口时出错:', error);
|
2025-05-07 13:46:48 +08:00
|
|
|
alert('保存接口失败: ' + error.message);
|
2025-04-28 12:25:20 +08:00
|
|
|
}
|
2025-04-30 14:50:27 +08:00
|
|
|
});
|
2025-05-07 13:46:48 +08:00
|
|
|
|
|
|
|
// 搜索事件
|
|
|
|
toolbar.addEventListener('search', (e) => {
|
|
|
|
const keyword = e.detail.keyword;
|
|
|
|
dataTable.dispatchEvent(new CustomEvent('search', {
|
|
|
|
detail: { keyword },
|
|
|
|
bubbles: true,
|
|
|
|
composed: true
|
|
|
|
}));
|
|
|
|
});
|
|
|
|
|
|
|
|
// 重置搜索事件
|
|
|
|
toolbar.addEventListener('reset-search', async () => {
|
|
|
|
// 重新加载数据
|
|
|
|
await this.loadData();
|
|
|
|
// 触发重置事件
|
|
|
|
dataTable.dispatchEvent(new CustomEvent('reset-search', {
|
|
|
|
bubbles: true,
|
|
|
|
composed: true
|
|
|
|
}));
|
|
|
|
});
|
|
|
|
|
|
|
|
// 高级搜索事件
|
|
|
|
toolbar.addEventListener('advanced-search', (e) => {
|
|
|
|
dataTable.dispatchEvent(new CustomEvent('advanced-search', {
|
|
|
|
detail: e.detail,
|
|
|
|
bubbles: true,
|
|
|
|
composed: true
|
|
|
|
}));
|
|
|
|
});
|
2025-04-28 12:25:20 +08:00
|
|
|
}
|
|
|
|
|
2025-04-30 14:50:27 +08:00
|
|
|
async loadData() {
|
2025-04-28 12:25:20 +08:00
|
|
|
try {
|
2025-05-16 10:26:07 +08:00
|
|
|
// 从 localStorage 获取选择
|
|
|
|
const savedSelection = localStorage.getItem('xnsim-selection');
|
|
|
|
if (!savedSelection) {
|
|
|
|
throw new Error('请先选择构型');
|
|
|
|
}
|
|
|
|
const selection = JSON.parse(savedSelection);
|
|
|
|
if (!selection.configurationId) {
|
|
|
|
throw new Error('请先选择构型');
|
|
|
|
}
|
|
|
|
|
|
|
|
const response = await fetch(`/api/interface/list?systemName=XNSim&confID=${selection.configurationId}`);
|
2025-04-28 12:25:20 +08:00
|
|
|
if (!response.ok) {
|
2025-04-30 14:50:27 +08:00
|
|
|
throw new Error('获取数据失败');
|
2025-04-28 12:25:20 +08:00
|
|
|
}
|
2025-04-30 14:50:27 +08:00
|
|
|
this.data = await response.json();
|
2025-05-07 13:46:48 +08:00
|
|
|
|
2025-05-16 10:26:07 +08:00
|
|
|
// 从接口数据中提取机型和ATA章节列表
|
|
|
|
this.planes = [...new Set(this.data.map(item => item.PlaneName))];
|
2025-05-07 13:46:48 +08:00
|
|
|
this.atas = [...new Set(this.data.map(item => item.ATAName))];
|
|
|
|
|
2025-04-30 14:50:27 +08:00
|
|
|
this.updateTable();
|
2025-05-07 13:46:48 +08:00
|
|
|
this.updateAdvancedSearchOptions();
|
|
|
|
|
|
|
|
// 通知所有子组件数据已更新
|
|
|
|
const importDialog = this.shadowRoot.querySelector('import-dialog');
|
|
|
|
if (importDialog) {
|
2025-05-16 10:26:07 +08:00
|
|
|
importDialog.setOptions(this.planes, this.atas);
|
2025-05-07 13:46:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const variableForm = this.shadowRoot.querySelector('variable-form');
|
|
|
|
if (variableForm) {
|
2025-05-16 10:26:07 +08:00
|
|
|
variableForm.setOptions(this.planes, this.atas);
|
2025-05-07 13:46:48 +08:00
|
|
|
}
|
2025-04-28 12:25:20 +08:00
|
|
|
} catch (error) {
|
2025-04-30 14:50:27 +08:00
|
|
|
console.error('加载数据时出错:', error);
|
2025-05-16 10:26:07 +08:00
|
|
|
alert(error.message || '加载数据失败');
|
2025-04-28 12:25:20 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-04-30 14:50:27 +08:00
|
|
|
updateTable() {
|
|
|
|
const dataTable = this.shadowRoot.querySelector('interface-data-table');
|
|
|
|
if (dataTable) {
|
|
|
|
dataTable.setData(this.data);
|
|
|
|
}
|
2025-04-28 12:25:20 +08:00
|
|
|
}
|
|
|
|
|
2025-05-07 13:46:48 +08:00
|
|
|
updateAdvancedSearchOptions() {
|
|
|
|
const toolbar = this.shadowRoot.querySelector('interface-toolbar');
|
|
|
|
if (!toolbar) return;
|
|
|
|
|
|
|
|
// 使用已提取的构型和ATA章节列表
|
|
|
|
const structs = [...new Set(this.data.map(item => item.ModelStructName))];
|
|
|
|
|
|
|
|
// 更新下拉选项
|
|
|
|
toolbar.updateFilterOptions({
|
2025-05-16 10:26:07 +08:00
|
|
|
planes: this.planes,
|
2025-05-07 13:46:48 +08:00
|
|
|
atas: this.atas,
|
|
|
|
structs
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2025-04-28 12:25:20 +08:00
|
|
|
render() {
|
|
|
|
this.shadowRoot.innerHTML = `
|
|
|
|
<style>
|
|
|
|
:host {
|
|
|
|
display: block;
|
|
|
|
height: 100%;
|
|
|
|
overflow: auto;
|
|
|
|
padding: 16px;
|
|
|
|
box-sizing: border-box;
|
|
|
|
font-family: Arial, sans-serif;
|
|
|
|
}
|
|
|
|
|
|
|
|
.config-container {
|
|
|
|
background-color: white;
|
|
|
|
border-radius: 8px;
|
|
|
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|
|
|
padding: 16px;
|
|
|
|
height: 100%;
|
|
|
|
box-sizing: border-box;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
gap: 16px;
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
<div class="config-container">
|
2025-04-30 14:50:27 +08:00
|
|
|
<interface-toolbar></interface-toolbar>
|
|
|
|
<interface-data-table></interface-data-table>
|
|
|
|
<variable-form></variable-form>
|
2025-05-07 13:46:48 +08:00
|
|
|
<import-dialog></import-dialog>
|
2025-04-28 12:25:20 +08:00
|
|
|
</div>
|
|
|
|
`;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-05-07 13:46:48 +08:00
|
|
|
customElements.define('interface-config', InterfaceConfig);
|