This commit is contained in:
2026-05-08 15:16:04 +08:00
parent 042b626ccb
commit 507fb9789a
71 changed files with 14944 additions and 0 deletions
+247
View File
@@ -0,0 +1,247 @@
{% extends "base.html" %}
{% block content %}
<section class="hero-panel compact page-header-compact">
<div class="hero-copy">
<p class="eyebrow">Engine Edit</p>
<h1>编辑 {{ family.engine_name }}</h1>
<p class="hero-text">支持家族字段编辑、配置项新增、配置项删除,以及整机删除。</p>
</div>
</section>
<section class="panel top-gap">
<div class="panel-heading">
<p class="eyebrow">Add Variant</p>
<h2>新增配置项</h2>
</div>
<form method="post" action="{{ url_for('web.engine_variant_add', family_id=family.id) }}" class="form-grid variant-add-grid">
{% for field in variant_create_fields %}
{% set input_name = 'add-' ~ field.name %}
<label>
<span class="field-label">{{ field.label }}</span>
{% if field.kind == 'combo' %}
{% set options = form_options.get(field.name, []) %}
<select name="{{ input_name }}" {% if field.required %}required{% endif %}>
<option value="">请选择</option>
{% for option in options %}
<option value="{{ option }}">{{ option }}</option>
{% endfor %}
<option value="{{ custom_option_value }}">新增选项</option>
</select>
<input
type="text"
name="{{ input_name }}__custom"
value=""
placeholder="没有合适选项时,在这里输入新的 {{ field.label }}"
>
{% else %}
<input
type="text"
name="{{ input_name }}"
value=""
{% if field.required %}required{% endif %}
>
{% endif %}
</label>
{% endfor %}
<div class="button-row">
<button class="primary-button" type="submit">新增配置</button>
</div>
</form>
</section>
<form method="post" class="edit-layout">
<section class="panel">
<div class="panel-heading">
<p class="eyebrow">Family</p>
<h2>基础字段</h2>
</div>
<div class="form-grid family-grid">
{% for field in family_fields %}
{% set current_value = family|attr(field.name) if family|attr(field.name) is not none else '' %}
<label>
<span class="field-label">{{ field.label }}</span>
{% if field.kind == 'combo' %}
{% set options = form_options.get(field.name, []) %}
{% set custom_value = '' if not current_value or current_value in options else current_value %}
<select name="{{ field.name }}" {% if field.required and not custom_value %}required{% endif %}>
<option value="">请选择</option>
{% for option in options %}
<option value="{{ option }}" {% if option == current_value %}selected{% endif %}>{{ option }}</option>
{% endfor %}
{% if custom_value %}
<option value="{{ custom_option_value }}" selected>新增选项</option>
{% else %}
<option value="{{ custom_option_value }}">新增选项</option>
{% endif %}
</select>
<input
type="text"
name="{{ field.name }}__custom"
value="{{ custom_value }}"
placeholder="没有合适选项时,在这里输入新的 {{ field.label }}"
>
{% else %}
<input
type="text"
name="{{ field.name }}"
value="{{ current_value }}"
{% if field.required %}required{% endif %}
>
{% endif %}
</label>
{% endfor %}
</div>
</section>
<section class="panel panel-wide">
<div class="panel-heading">
<p class="eyebrow">Variants</p>
<h2>配置字段</h2>
</div>
<div class="variant-editor-stack">
{% for variant in family.variants %}
<article class="variant-editor" data-engine-calculator>
<div class="module-meta">
<h3>{{ variant.config_name or "Default" }}</h3>
<div class="button-row compact-row">
<span class="chip">Row {{ variant.source_sheet_row or "-" }}</span>
<button
class="danger-link"
type="submit"
formaction="{{ url_for('web.engine_variant_delete', family_id=family.id, variant_id=variant.id) }}"
formmethod="post"
formnovalidate
onclick="return confirm('确认删除这个配置项?')"
>删除配置</button>
</div>
</div>
<div class="form-grid variant-editor-grid">
{% for field in variant_fields %}
{% set current_value = variant|attr(field.name) %}
{% set input_name = 'variant-' ~ variant.id ~ '-' ~ field.name %}
{% if field.kind == 'textarea' %}
<label class="field-span-two">
<span class="field-label">{{ field.label }}</span>
<textarea name="{{ input_name }}" rows="3">{{ current_value if current_value is not none else '' }}</textarea>
</label>
{% elif field.kind == 'checkbox' %}
<label class="checkbox-row field-span-two">
<input type="checkbox" name="{{ input_name }}" {% if current_value %}checked{% endif %}>
<span>{{ field.label }}</span>
</label>
{% elif field.kind == 'combo' %}
<label>
<span class="field-label">{{ field.label }}</span>
{% set options = form_options.get(field.name, []) %}
{% set normalized_value = current_value if current_value is not none else '' %}
{% set custom_value = '' if not normalized_value or normalized_value in options else normalized_value %}
<select name="{{ input_name }}" {% if field.required and not custom_value %}required{% endif %}>
<option value="">请选择</option>
{% for option in options %}
<option value="{{ option }}" {% if option == normalized_value %}selected{% endif %}>{{ option }}</option>
{% endfor %}
{% if custom_value %}
<option value="{{ custom_option_value }}" selected>新增选项</option>
{% else %}
<option value="{{ custom_option_value }}">新增选项</option>
{% endif %}
</select>
<input
type="text"
name="{{ input_name }}__custom"
value="{{ custom_value }}"
placeholder="没有合适选项时,在这里输入新的 {{ field.label }}"
>
</label>
{% else %}
<label>
<span class="field-label">{{ field.label }}</span>
<input
type="text"
name="{{ input_name }}"
value="{{ current_value if current_value is not none else '' }}"
{% if field.name in ['min_thrust_kn', 'max_thrust_kn', 'mass_t', 'twr', 'throttle_ratio'] %}data-calc-field="{{ field.name }}"{% endif %}
{% if field.required %}required{% endif %}
{% if field.name in ['twr', 'throttle_ratio'] %}readonly{% endif %}
>
</label>
{% endif %}
{% endfor %}
</div>
</article>
{% endfor %}
</div>
<div class="button-row top-gap">
<button class="primary-button" type="submit">保存修改</button>
<a class="secondary-button" href="{{ url_for('web.engine_detail', family_id=family.id) }}">取消</a>
<button
class="danger-link"
type="submit"
formaction="{{ url_for('web.engine_delete', family_id=family.id) }}"
formmethod="post"
formnovalidate
onclick="return confirm('确认删除整个引擎 {{ family.engine_name }} ?')"
>删除整个引擎</button>
</div>
</section>
</form>
<script>
(() => {
const gravity = 9.80665;
const formatDecimal = (value) => {
if (!Number.isFinite(value)) {
return "";
}
return value.toFixed(4).replace(/\.?0+$/, "");
};
const parseNumber = (input) => {
if (!input) {
return null;
}
const cleaned = input.value.trim();
if (!cleaned) {
return null;
}
const parsed = Number(cleaned);
return Number.isFinite(parsed) ? parsed : null;
};
const recalculate = (container) => {
const maxThrustInput = container.querySelector('[data-calc-field="max_thrust_kn"]');
const minThrustInput = container.querySelector('[data-calc-field="min_thrust_kn"]');
const massInput = container.querySelector('[data-calc-field="mass_t"]');
const twrInput = container.querySelector('[data-calc-field="twr"]');
const throttleRatioInput = container.querySelector('[data-calc-field="throttle_ratio"]');
const maxThrust = parseNumber(maxThrustInput);
const minThrust = parseNumber(minThrustInput);
const mass = parseNumber(massInput);
if (twrInput) {
twrInput.value = maxThrust !== null && mass !== null && mass !== 0
? formatDecimal(maxThrust / gravity / mass)
: "";
}
if (throttleRatioInput) {
throttleRatioInput.value = minThrust !== null && maxThrust !== null && maxThrust !== 0
? formatDecimal(minThrust / maxThrust)
: "";
}
};
document.querySelectorAll('[data-engine-calculator]').forEach((container) => {
container.querySelectorAll('[data-calc-field="min_thrust_kn"], [data-calc-field="max_thrust_kn"], [data-calc-field="mass_t"]').forEach((input) => {
input.addEventListener('input', () => recalculate(container));
});
recalculate(container);
});
})();
</script>
{% endblock %}