457 lines
18 KiB
JavaScript
Raw Normal View History

class VariableForm extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.mode = 'add';
this.interfaceData = null;
2025-05-07 13:46:48 +08:00
this.products = [];
this.ataChapters = [];
this.modelStructs = [];
}
connectedCallback() {
this.render();
this.addEventListeners();
}
2025-05-07 13:46:48 +08:00
// 接收父组件传递的选项数据
setOptions(products, atas) {
this.products = products;
this.ataChapters = atas;
this.updateProductOptions();
this.updateAtaOptions();
}
updateProductOptions() {
const select = this.shadowRoot.querySelector('#productName');
if (select) {
select.innerHTML = `
<option value="">请选择构型</option>
${this.products.map(product => `
<option value="${product}" ${this.interfaceData?.ProductName === product ? 'selected' : ''}>
${product}
</option>
`).join('')}
`;
}
}
updateAtaOptions() {
const select = this.shadowRoot.querySelector('#ataName');
if (select) {
select.innerHTML = `
<option value="">请选择ATA章节</option>
${this.ataChapters.map(chapter => `
<option value="${chapter}" ${this.interfaceData?.ATAName === chapter ? 'selected' : ''}>
${chapter}
</option>
`).join('')}
`;
}
}
async loadModelStructs(productName, ataName) {
try {
const response = await fetch(`/api/interface/struct/list?systemName=XNSim&productName=${productName}&ataName=${ataName}`);
if (!response.ok) {
throw new Error('获取模型结构体列表失败');
}
const data = await response.json();
this.modelStructs = data.map(item => item.ModelStructName);
this.updateModelStructSelect();
} catch (error) {
console.error('加载模型结构体列表失败:', error);
alert('加载模型结构体列表失败');
}
}
updateModelStructSelect() {
const select = this.shadowRoot.querySelector('#modelStructName');
if (select) {
select.innerHTML = `
<option value="">请选择模型结构体</option>
${this.modelStructs.map(struct => `
<option value="${struct}" ${this.interfaceData?.ModelStructName === struct ? 'selected' : ''}>
${struct}
</option>
`).join('')}
`;
}
}
setMode(mode, data = null) {
this.mode = mode;
this.interfaceData = data;
2025-05-07 13:46:48 +08:00
if (data) {
// 保存原始数据
this.originalData = {
ProductName: data.ProductName,
ATAName: data.ATAName,
ModelStructName: data.ModelStructName,
InterfaceName: data.InterfaceName
};
// 如果是在编辑模式下,需要先加载模型结构体列表
this.loadModelStructs(data.ProductName, data.ATAName).then(() => {
this.render();
this.addEventListeners();
this.show();
});
} else {
this.render();
this.addEventListeners();
this.show();
}
}
show() {
2025-05-07 13:46:48 +08:00
const overlay = this.shadowRoot.querySelector('.form-overlay');
if (overlay) {
overlay.style.display = 'block';
}
}
hide() {
2025-05-07 13:46:48 +08:00
const overlay = this.shadowRoot.querySelector('.form-overlay');
if (overlay) {
overlay.style.display = 'none';
}
}
addEventListeners() {
const form = this.shadowRoot.querySelector('form');
const cancelBtn = this.shadowRoot.querySelector('.cancel-btn');
2025-05-07 13:46:48 +08:00
const productSelect = this.shadowRoot.querySelector('#productName');
const ataSelect = this.shadowRoot.querySelector('#ataName');
const interfaceNameInput = this.shadowRoot.querySelector('#interfaceName');
const isArrayCheckbox = this.shadowRoot.querySelector('#interfaceIsArray');
const arraySize1Input = this.shadowRoot.querySelector('#interfaceArraySize_1');
const arraySize2Input = this.shadowRoot.querySelector('#interfaceArraySize_2');
// 监听构型和ATA章节的变化
productSelect.addEventListener('change', () => {
const productName = productSelect.value;
const ataName = ataSelect.value;
if (productName && ataName) {
this.loadModelStructs(productName, ataName);
}
});
ataSelect.addEventListener('change', () => {
const productName = productSelect.value;
const ataName = ataSelect.value;
if (productName && ataName) {
this.loadModelStructs(productName, ataName);
}
});
// 验证C++命名规范
interfaceNameInput.addEventListener('input', (e) => {
const value = e.target.value;
// C++命名规范:以字母或下划线开头,只能包含字母、数字和下划线
const isValid = /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(value);
if (!isValid) {
e.target.setCustomValidity('接口名称必须以字母或下划线开头,只能包含字母、数字和下划线');
} else {
e.target.setCustomValidity('');
}
});
// 验证数组大小
arraySize1Input.addEventListener('input', (e) => {
const value = parseInt(e.target.value);
if (value <= 1) {
e.target.setCustomValidity('第一维大小必须大于1');
} else {
e.target.setCustomValidity('');
}
});
arraySize2Input.addEventListener('input', (e) => {
const value = e.target.value;
if (value && parseInt(value) <= 1 && parseInt(value) !== 0) {
e.target.setCustomValidity('第二维大小必须大于1');
} else {
e.target.setCustomValidity('');
}
});
form.addEventListener('submit', (e) => {
e.preventDefault();
2025-05-07 13:46:48 +08:00
const formData = new FormData(form);
2025-05-07 13:46:48 +08:00
const data = {
SystemName: 'XNSim',
ProductName: formData.get('productName'),
ATAName: formData.get('ataName'),
ModelStructName: formData.get('modelStructName'),
InterfaceName: formData.get('interfaceName'),
InterfaceType: formData.get('interfaceType'),
2025-05-07 13:46:48 +08:00
InterfaceOption: 1,
InterfaceIsArray: formData.get('interfaceIsArray') ? 1 : 0,
InterfaceArraySize_1: formData.get('interfaceArraySize_1'),
InterfaceArraySize_2: formData.get('interfaceArraySize_2'),
InterfaceNotes: formData.get('interfaceNotes')
};
2025-05-07 13:46:48 +08:00
// 如果是编辑模式,添加原始数据
if (this.mode === 'edit' && this.originalData) {
data.originalProductName = this.originalData.ProductName;
data.originalATAName = this.originalData.ATAName;
data.originalModelStructName = this.originalData.ModelStructName;
data.originalInterfaceName = this.originalData.InterfaceName;
}
// 验证必填字段
const requiredFields = [
'SystemName',
'ProductName',
'ATAName',
'ModelStructName',
'InterfaceName',
'InterfaceType'
];
const missingFields = requiredFields.filter(field => !data[field]);
if (missingFields.length > 0) {
alert(`请填写以下必填字段:${missingFields.join(', ')}`);
return;
}
// 如果是数组类型,验证数组大小
if (data.InterfaceIsArray === 1) {
if (!data.InterfaceArraySize_1 || data.InterfaceArraySize_1 <= 1) {
alert('第一维大小必须大于1');
return;
}
2025-05-07 13:46:48 +08:00
if (data.InterfaceArraySize_2 && data.InterfaceArraySize_2 <= 1 && data.InterfaceArraySize_2 !== 0) {
alert('第二维大小必须大于1或等于0');
return;
}
}
this.dispatchEvent(new CustomEvent('save-success', {
detail: { ...data, mode: this.mode }
}));
2025-05-07 13:46:48 +08:00
this.hide();
});
2025-05-07 13:46:48 +08:00
cancelBtn.addEventListener('click', () => {
this.hide();
});
2025-05-07 13:46:48 +08:00
// 监听数组大小输入框的变化
isArrayCheckbox.addEventListener('change', () => {
arraySize1Input.disabled = !isArrayCheckbox.checked;
arraySize2Input.disabled = !isArrayCheckbox.checked;
if (!isArrayCheckbox.checked) {
arraySize1Input.value = '';
arraySize2Input.value = '';
}
});
}
render() {
2025-05-07 13:46:48 +08:00
const interfaceTypes = [
'char', 'octet', 'short', 'unsigned short',
'long', 'unsigned long', 'long long', 'unsigned long long',
'float', 'double', 'long double', 'boolean'
];
this.shadowRoot.innerHTML = `
<style>
2025-05-07 13:46:48 +08:00
.form-overlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1000;
}
2025-05-07 13:46:48 +08:00
.form-container {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: white;
padding: 20px;
border-radius: 8px;
2025-05-07 13:46:48 +08:00
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
width: 500px;
max-height: 90vh;
overflow-y: auto;
}
.form-title {
2025-05-07 13:46:48 +08:00
margin: 0 0 20px 0;
font-size: 18px;
font-weight: bold;
}
.form-group {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
2025-05-07 13:46:48 +08:00
select, input[type="text"], input[type="number"] {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
box-sizing: border-box;
}
2025-05-07 13:46:48 +08:00
.checkbox-group {
display: flex;
align-items: center;
gap: 5px;
}
2025-05-07 13:46:48 +08:00
.checkbox-group input[type="checkbox"] {
width: auto;
}
.button-group {
display: flex;
justify-content: flex-end;
gap: 10px;
margin-top: 20px;
}
2025-05-07 13:46:48 +08:00
button {
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
}
.save-btn {
background-color: #4CAF50;
color: white;
}
.cancel-btn {
background-color: #f44336;
color: white;
}
2025-05-07 13:46:48 +08:00
button:hover {
opacity: 0.9;
}
.array-size-group {
display: flex;
gap: 10px;
align-items: center;
}
.array-size-group input[type="number"] {
width: 100px;
}
</style>
2025-05-07 13:46:48 +08:00
<div class="form-overlay">
<div class="form-container">
<h2 class="form-title">${this.mode === 'add' ? '添加接口' : '编辑接口'}</h2>
<form>
<div class="form-group">
2025-05-07 13:46:48 +08:00
<label for="productName">构型</label>
<select id="productName" name="productName" required>
<option value="">请选择构型</option>
${this.products.map(product => `
<option value="${product}" ${this.interfaceData?.ProductName === product ? 'selected' : ''}>
${product}
</option>
`).join('')}
</select>
</div>
2025-05-07 13:46:48 +08:00
<div class="form-group">
2025-05-07 13:46:48 +08:00
<label for="ataName">ATA章节</label>
<select id="ataName" name="ataName" required>
<option value="">请选择ATA章节</option>
${this.ataChapters.map(chapter => `
<option value="${chapter}" ${this.interfaceData?.ATAName === chapter ? 'selected' : ''}>
${chapter}
</option>
`).join('')}
</select>
</div>
2025-05-07 13:46:48 +08:00
<div class="form-group">
2025-05-07 13:46:48 +08:00
<label for="modelStructName">接口结构体名</label>
<select id="modelStructName" name="modelStructName" required>
<option value="">请选择接口结构体</option>
${this.modelStructs.map(struct => `
<option value="${struct}" ${this.interfaceData?.ModelStructName === struct ? 'selected' : ''}>
${struct}
</option>
`).join('')}
</select>
</div>
2025-05-07 13:46:48 +08:00
<div class="form-group">
2025-05-07 13:46:48 +08:00
<label for="interfaceName">接口名称</label>
<input type="text" id="interfaceName" name="interfaceName" required
value="${this.interfaceData?.InterfaceName || ''}">
</div>
2025-05-07 13:46:48 +08:00
<div class="form-group">
2025-05-07 13:46:48 +08:00
<label for="interfaceType">数据类型</label>
<select id="interfaceType" name="interfaceType" required>
<option value="">请选择数据类型</option>
${interfaceTypes.map(type => `
<option value="${type}" ${this.interfaceData?.InterfaceType === type ? 'selected' : ''}>
${type}
</option>
`).join('')}
</select>
</div>
2025-05-07 13:46:48 +08:00
<div class="form-group">
2025-05-07 13:46:48 +08:00
<div class="checkbox-group">
<input type="checkbox" id="interfaceIsArray" name="interfaceIsArray"
${this.interfaceData?.InterfaceIsArray === 1 ? 'checked' : ''}>
<label for="interfaceIsArray">是否为数组</label>
</div>
</div>
2025-05-07 13:46:48 +08:00
<div class="form-group">
2025-05-07 13:46:48 +08:00
<label>数组大小</label>
<div class="array-size-group">
<input type="number" id="interfaceArraySize_1" name="interfaceArraySize_1"
value="${this.interfaceData?.InterfaceArraySize_1 || ''}"
${this.interfaceData?.InterfaceIsArray !== 1 ? 'disabled' : ''}
placeholder="第一维">
<span>×</span>
<input type="number" id="interfaceArraySize_2" name="interfaceArraySize_2"
value="${this.interfaceData?.InterfaceArraySize_2 || ''}"
${this.interfaceData?.InterfaceIsArray !== 1 ? 'disabled' : ''}
placeholder="第二维">
</div>
</div>
2025-05-07 13:46:48 +08:00
<div class="form-group">
2025-05-07 13:46:48 +08:00
<label for="interfaceNotes">备注</label>
<input type="text" id="interfaceNotes" name="interfaceNotes"
value="${this.interfaceData?.InterfaceNotes || ''}">
</div>
2025-05-07 13:46:48 +08:00
<div class="button-group">
<button type="button" class="cancel-btn">取消</button>
<button type="submit" class="save-btn">保存</button>
</div>
</form>
</div>
</div>
`;
}
}
customElements.define('variable-form', VariableForm);