update
This commit is contained in:
@@ -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 %}
|
||||
Reference in New Issue
Block a user