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-07 13:46:48 +08:00
|
|
|
this.products = []; // 存储构型列表
|
|
|
|
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-07 13:46:48 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
2025-04-30 14:50:27 +08:00
|
|
|
const deletePromises = selectedRows.map(row => {
|
|
|
|
const { SystemName, ProductName, ATAName, ModelStructName, InterfaceName } = row;
|
|
|
|
return fetch(`/api/interface/delete?systemName=${SystemName}&productName=${ProductName}&ataName=${ATAName}&modelStructName=${ModelStructName}&interfaceName=${InterfaceName}`, {
|
|
|
|
method: 'DELETE'
|
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);
|
|
|
|
alert('删除接口失败');
|
2025-04-28 12:25:20 +08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2025-04-30 14:50:27 +08:00
|
|
|
// 下载模板事件
|
|
|
|
toolbar.addEventListener('download-template', async () => {
|
|
|
|
try {
|
|
|
|
const response = await fetch('/api/interface/template');
|
|
|
|
if (!response.ok) {
|
|
|
|
throw new Error('下载模板失败');
|
2025-04-28 12:25:20 +08:00
|
|
|
}
|
2025-04-30 14:50:27 +08:00
|
|
|
|
|
|
|
const blob = await response.blob();
|
|
|
|
const url = window.URL.createObjectURL(blob);
|
|
|
|
const a = document.createElement('a');
|
|
|
|
a.href = url;
|
|
|
|
a.download = '接口变量模板.xlsx';
|
|
|
|
document.body.appendChild(a);
|
|
|
|
a.click();
|
|
|
|
document.body.removeChild(a);
|
|
|
|
window.URL.revokeObjectURL(url);
|
|
|
|
} catch (error) {
|
|
|
|
console.error('下载模板时出错:', error);
|
|
|
|
alert('下载模板失败');
|
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 {
|
|
|
|
console.log('准备导入的数据:', importData);
|
|
|
|
|
|
|
|
const response = await fetch('/api/interface/import', {
|
|
|
|
method: 'POST',
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
},
|
|
|
|
body: JSON.stringify(importData)
|
|
|
|
});
|
|
|
|
|
|
|
|
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);
|
|
|
|
alert('保存导入数据失败: ' + error.message);
|
|
|
|
}
|
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) {
|
|
|
|
// 确保在设置编辑数据之前先设置选项
|
|
|
|
variableForm.setOptions(this.products, this.atas);
|
|
|
|
// 先显示表单,再设置模式和数据
|
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) => {
|
|
|
|
const { SystemName, ProductName, ATAName, ModelStructName, InterfaceName } = e.detail;
|
|
|
|
|
|
|
|
try {
|
|
|
|
const response = await fetch(`/api/interface/delete?systemName=${SystemName}&productName=${ProductName}&ataName=${ATAName}&modelStructName=${ModelStructName}&interfaceName=${InterfaceName}`, {
|
|
|
|
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);
|
|
|
|
alert('删除接口失败');
|
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',
|
|
|
|
ProductName: interfaceData.ProductName,
|
|
|
|
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,
|
|
|
|
InterfaceNotes: interfaceData.InterfaceNotes
|
|
|
|
},
|
|
|
|
originalData: {
|
|
|
|
SystemName: 'XNSim',
|
|
|
|
ProductName: interfaceData.originalProductName || interfaceData.ProductName,
|
|
|
|
ATAName: interfaceData.originalATAName || interfaceData.ATAName,
|
|
|
|
ModelStructName: interfaceData.originalModelStructName || interfaceData.ModelStructName,
|
|
|
|
InterfaceName: interfaceData.originalInterfaceName || interfaceData.InterfaceName
|
|
|
|
}
|
|
|
|
} : {
|
|
|
|
SystemName: 'XNSim',
|
|
|
|
ProductName: interfaceData.ProductName,
|
|
|
|
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,
|
|
|
|
InterfaceNotes: interfaceData.InterfaceNotes
|
|
|
|
};
|
|
|
|
|
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-04-30 14:50:27 +08:00
|
|
|
const response = await fetch('/api/interface/list');
|
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
|
|
|
|
|
|
|
// 从接口数据中提取构型和ATA章节列表
|
|
|
|
this.products = [...new Set(this.data.map(item => item.ProductName))];
|
|
|
|
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) {
|
|
|
|
importDialog.setOptions(this.products, this.atas);
|
|
|
|
}
|
|
|
|
|
|
|
|
const variableForm = this.shadowRoot.querySelector('variable-form');
|
|
|
|
if (variableForm) {
|
|
|
|
variableForm.setOptions(this.products, this.atas);
|
|
|
|
}
|
2025-04-28 12:25:20 +08:00
|
|
|
} catch (error) {
|
2025-04-30 14:50:27 +08:00
|
|
|
console.error('加载数据时出错:', error);
|
|
|
|
alert('加载数据失败');
|
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({
|
|
|
|
products: this.products,
|
|
|
|
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);
|