Commit 60ce94e1 authored by 郭阔's avatar 郭阔

ui(schedules): 排程抽屉竖排改版+当前实际时间回显

- 抽屉改为分行布局:当前定时(chips)/采集频率/第N次逐行+实际时间列,
  不再一行平铺;加收起按钮
- 回显:schedule_board 将实际定时按时段归类(与规划器同口径)对应到各次意图;
  未配置时段意图的源按实际时间归类生成回显(所见即所排)
parent 1ae46160
......@@ -1327,8 +1327,19 @@ def schedule_board():
freqs = plan_conf.get("frequencies", {})
wins = plan_conf.get("windows", {})
def _runs_of(n):
f = freqs.get(n, 1)
def _window_of(t):
h, m = t.split(":")
v = int(h) * 60 + int(m)
if v < 6 * 60 or v > 21 * 60 + 30:
return "overnight"
if v < 12 * 60:
return "morning"
if v < 18 * 60:
return "afternoon"
return "evening"
def _runs_of(n, times):
f = freqs.get(n, len(times) or 1)
w = wins.get(n)
if isinstance(w, list):
rs = [x for x in w if x in ("overnight", "morning", "afternoon", "evening")]
......@@ -1336,13 +1347,27 @@ def schedule_board():
rs = [w] if f == 1 else ["overnight"] + [w] * (f - 1)
else:
rs = []
if not rs and times:
# 未配置时段意图:按当前实际时间归类回显(所见即所排)
rs = [_window_of(t) for t in sorted(times)]
while len(rs) < f:
rs.append("overnight")
return rs[:f]
for r in rows:
n = r["name"]
r["intent"] = {"freq": freqs.get(n, len(r["times"]) or 1), "runs": _runs_of(n)}
r["intent"] = {"freq": freqs.get(n, len(r["times"]) or 1), "runs": _runs_of(n, r["times"])}
# 回显:当前实际定时按时段归类(与规划器同口径),依次对应到各次意图;
# 对不上的次(手改过时间/未排)留空,抽屉里显示 —
for r in rows:
buckets = {}
for t in sorted(r["times"]):
buckets.setdefault(_window_of(t), []).append(t)
r["intent"]["echo"] = [
buckets[w].pop(0) if buckets.get(w) else ""
for w in r["intent"]["runs"]
]
return render_template("schedules.html", rows=rows, now=now,
digest_next=_next_fire(digest_times, now),
digest_times=digest_times,
......
......@@ -30,7 +30,12 @@ function toggleEdit(name) {
.opsbar { display:flex; gap:4px; white-space:nowrap; }
.opsbar form { display:inline; margin:0; }
tr.drawer > td { background:#161923; border-top:1px dashed #2a2d37; padding:12px 16px; }
tr.drawer .hint { color:#888; font-size:12px; margin-bottom:8px; }
.drawer-box { max-width:620px; }
.drow { display:flex; align-items:center; gap:10px; margin:8px 0; }
.dlabel { display:inline-block; width:72px; color:#888; flex:none; }
.tchip { background:#1e2230; border:1px solid #2a2d37; border-radius:4px; padding:2px 10px; font-family:monospace; color:#d4d4d4; }
.decho { color:#e8c34a; font-family:monospace; min-width:44px; }
.dnote { color:#666; font-size:12px; margin-left:12px; }
</style>
{% endblock %}
{% block content %}
......@@ -136,27 +141,42 @@ function toggleEdit(name) {
</tr>
<tr id="edit-{{ r.name }}" class="drawer" style="display:none">
<td colspan="6">
<div class="hint">排程意图:选频率和各次时段,保存后自动按交付线/全局间隔重排全部源的时间。</div>
<form method="POST" action="{{ url_for('schedule_intent') }}" style="white-space:nowrap">
<input type="hidden" name="name" value="{{ r.name }}">
<select name="freq" class="intsel" onchange="toggleRuns(this)"
style="background:#1a1d27;border:1px solid #2a2d37;border-radius:4px;color:#d4d4d4;padding:3px 6px">
{% for f in [1,2,3,4,5,6] %}
<option value="{{ f }}" {% if r.intent.freq == f %}selected{% endif %}>每日 {{ f }} 次</option>
<div class="drawer-box">
<div class="drow">
<span class="dlabel">当前定时</span>
{% if r.times %}{% for t in r.times %}<span class="tchip">{{ t }}</span>{% endfor %}
{% else %}<span style="color:#666">未排程</span>{% endif %}
<span class="dnote">保存后自动按交付线与全局间隔重排全部源</span>
</div>
<form method="POST" action="{{ url_for('schedule_intent') }}">
<input type="hidden" name="name" value="{{ r.name }}">
<div class="drow">
<span class="dlabel">采集频率</span>
<select name="freq" class="intsel" onchange="toggleRuns(this)"
style="background:#1a1d27;border:1px solid #2a2d37;border-radius:4px;color:#d4d4d4;padding:3px 6px">
{% for f in [1,2,3,4,5,6] %}
<option value="{{ f }}" {% if r.intent.freq == f %}selected{% endif %}>每日 {{ f }} 次</option>
{% endfor %}
</select>
<span class="dlabel" style="width:auto;margin-left:24px">实际时间</span>
</div>
{% for i in range(1,7) %}
<div class="drow runwin" data-i="{{ i }}" style="{% if i > r.intent.freq %}display:none;{% endif %}margin-left:28px">
<span class="dlabel">第 {{ i }} 次</span>
<select name="window_{{ i }}" style="background:#1a1d27;border:1px solid #2a2d37;border-radius:4px;color:#d4d4d4;padding:3px 8px">
{% for v, lbl in [('overnight','凌晨批次'),('morning','上午'),('afternoon','下午'),('evening','晚间')] %}
<option value="{{ v }}" {% if r.intent.runs[i-1] == v %}selected{% endif %}>{{ lbl }}</option>
{% endfor %}
</select>
<span class="decho">{{ r.intent.echo[i-1] or '—' }}</span>
</div>
{% endfor %}
</select>
{% for i in range(1,7) %}
<span class="runwin" data-i="{{ i }}" style="{% if i > r.intent.freq %}display:none;{% endif %}margin-left:8px">
第{{ i }}次
<select name="window_{{ i }}" style="background:#1a1d27;border:1px solid #2a2d37;border-radius:4px;color:#d4d4d4;padding:3px 4px">
{% for v, lbl in [('overnight','凌晨批次'),('morning','上午'),('afternoon','下午'),('evening','晚间')] %}
<option value="{{ v }}" {% if r.intent.runs[i-1] == v %}selected{% endif %}>{{ lbl }}</option>
{% endfor %}
</select>
</span>
{% endfor %}
<button type="submit" class="btn btn-primary" style="margin-left:10px">保存并重排</button>
</form>
<div class="drow" style="margin-left:28px">
<button type="submit" class="btn btn-primary">保存并重排</button>
<button type="button" class="btn" onclick="toggleEdit('{{ r.name }}')">收起</button>
</div>
</form>
</div>
</td>
</tr>
{% endfor %}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment