248 lines
11 KiB
HTML
248 lines
11 KiB
HTML
{% 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 %}
|