488 lines
19 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

class VariableForm extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.mode = 'add';
this.interfaceData = null;
this.planes = [];
this.ataChapters = [];
this.modelStructs = [];
}
connectedCallback() {
this.render();
this.addEventListeners();
}
// 接收父组件传递的选项数据
setOptions(planes, atas) {
this.planes = planes;
this.ataChapters = atas;
this.updatePlaneOptions();
this.updateAtaOptions();
}
updatePlaneOptions() {
const select = this.shadowRoot.querySelector('#planeName');
if (select) {
select.innerHTML = `
<option value="">请选择机型</option>
${this.planes.map(plane => `
<option value="${plane}" ${this.interfaceData?.PlaneName === plane ? 'selected' : ''}>
${plane}
</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(planeName, ataName) {
try {
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/struct/list?systemName=XNSim&planeName=${planeName}&ataName=${ataName}&confID=${selection.configurationId}`);
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(error.message || '加载模型结构体列表失败');
}
}
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;
if (data) {
// 保存原始数据
this.originalData = {
PlaneName: data.PlaneName,
ATAName: data.ATAName,
ModelStructName: data.ModelStructName,
InterfaceName: data.InterfaceName
};
// 如果是在编辑模式下,需要先加载模型结构体列表
this.loadModelStructs(data.PlaneName, data.ATAName).then(() => {
this.render();
this.addEventListeners();
this.show();
});
} else {
this.render();
this.addEventListeners();
this.show();
}
}
show() {
const overlay = this.shadowRoot.querySelector('.form-overlay');
if (overlay) {
overlay.style.display = 'block';
}
}
hide() {
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');
const planeSelect = this.shadowRoot.querySelector('#planeName');
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章节的变化
planeSelect.addEventListener('change', () => {
const planeName = planeSelect.value;
const ataName = ataSelect.value;
if (planeName && ataName) {
this.loadModelStructs(planeName, ataName);
}
});
ataSelect.addEventListener('change', () => {
const planeName = planeSelect.value;
const ataName = ataSelect.value;
if (planeName && ataName) {
this.loadModelStructs(planeName, 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();
const formData = new FormData(form);
const isArray = formData.get('interfaceIsArray') ? 1 : 0;
const arraySize1 = parseInt(formData.get('interfaceArraySize_1')) || 0;
const arraySize2 = parseInt(formData.get('interfaceArraySize_2')) || 0;
const data = {
SystemName: 'XNSim',
PlaneName: formData.get('planeName'),
ATAName: formData.get('ataName'),
ModelStructName: formData.get('modelStructName'),
InterfaceName: formData.get('interfaceName'),
InterfaceType: formData.get('interfaceType'),
InterfaceOption: 1,
InterfaceIsArray: isArray,
InterfaceArraySize_1: isArray && arraySize1 > 1 ? arraySize1 : 0,
InterfaceArraySize_2: isArray && arraySize1 > 1 ? arraySize2 : 0,
InterfaceNotes: formData.get('interfaceNotes')
};
// 从 localStorage 获取 ConfID
const savedSelection = localStorage.getItem('xnsim-selection');
if (!savedSelection) {
alert('请先选择机型');
return;
}
const selection = JSON.parse(savedSelection);
if (!selection.configurationId) {
alert('请先选择机型');
return;
}
data.ConfID = selection.configurationId;
// 如果是编辑模式,添加原始数据
if (this.mode === 'edit' && this.originalData) {
data.originalPlaneName = this.originalData.PlaneName;
data.originalATAName = this.originalData.ATAName;
data.originalModelStructName = this.originalData.ModelStructName;
data.originalInterfaceName = this.originalData.InterfaceName;
}
// 验证必填字段
const requiredFields = [
'SystemName',
'PlaneName',
'ATAName',
'ModelStructName',
'InterfaceName',
'InterfaceType',
'ConfID'
];
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;
}
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 }
}));
this.hide();
});
cancelBtn.addEventListener('click', () => {
this.hide();
});
// 监听数组大小输入框的变化
isArrayCheckbox.addEventListener('change', () => {
arraySize1Input.disabled = !isArrayCheckbox.checked;
arraySize2Input.disabled = !isArrayCheckbox.checked;
if (!isArrayCheckbox.checked) {
arraySize1Input.value = '';
arraySize2Input.value = '';
}
});
}
render() {
const interfaceTypes = [
'char', 'octet', 'short', 'unsigned short',
'long', 'unsigned long', 'long long', 'unsigned long long',
'float', 'double', 'long double', 'boolean'
];
// 从 localStorage 获取机型信息
const savedSelection = localStorage.getItem('xnsim-selection');
const selection = savedSelection ? JSON.parse(savedSelection) : null;
const planeName = selection?.plane || '';
this.shadowRoot.innerHTML = `
<style>
.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;
}
.form-container {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
width: 500px;
max-height: 90vh;
overflow-y: auto;
}
.form-title {
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;
}
select, input[type="text"], input[type="number"] {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
box-sizing: border-box;
}
.checkbox-group {
display: flex;
align-items: center;
gap: 5px;
}
.checkbox-group input[type="checkbox"] {
width: auto;
}
.button-group {
display: flex;
justify-content: flex-end;
gap: 10px;
margin-top: 20px;
}
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;
}
button:hover {
opacity: 0.9;
}
.array-size-group {
display: flex;
gap: 10px;
align-items: center;
}
.array-size-group input[type="number"] {
width: 100px;
}
.plane-info {
background-color: #f5f5f5;
padding: 10px;
border-radius: 4px;
margin-bottom: 15px;
}
</style>
<div class="form-overlay">
<div class="form-container">
<h2 class="form-title">${this.mode === 'add' ? '添加接口' : '编辑接口'}</h2>
<div class="plane-info">
当前机型:${planeName}
</div>
<form>
<input type="hidden" id="planeName" name="planeName" value="${planeName}">
<div class="form-group">
<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>
<div class="form-group">
<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>
<div class="form-group">
<label for="interfaceName">接口名称</label>
<input type="text" id="interfaceName" name="interfaceName" required
value="${this.interfaceData?.InterfaceName || ''}">
</div>
<div class="form-group">
<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>
<div class="form-group">
<div class="checkbox-group">
<input type="checkbox" id="interfaceIsArray" name="interfaceIsArray"
${this.interfaceData?.InterfaceIsArray === 1 ? 'checked' : ''}>
<label for="interfaceIsArray">是否为数组</label>
</div>
</div>
<div class="form-group">
<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>
<div class="form-group">
<label for="interfaceNotes">备注</label>
<input type="text" id="interfaceNotes" name="interfaceNotes"
value="${this.interfaceData?.InterfaceNotes || ''}">
</div>
<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);