Commit 86cc8a75 authored by 郭阔's avatar 郭阔

feat(schedules): 排程抽屉支持手动输入时间,冲突直接拒绝保存

- 抽屉新增"手动时间"输入框(HH:MM 逗号分隔,回填当前值),走 /schedule-time
- 服务端硬校验:与其他源任一时间或自身多次间隔不足全局最小间隔(24h 回环绕算)
  → 拒绝保存并列出全部冲突明细(与谁、差多少),不弹确认框
- 实测:02:10 提交被拦并列出与 business 02:00/markets 02:30 冲突,排程未变;
  无冲突时间正常保存
parent b1dec942
......@@ -1463,6 +1463,41 @@ def schedule_time_set():
if name in _active_harvests():
flash(f"{name} 正在采集,请等任务结束后再改时间", "error")
return redirect(url_for("schedule_board"))
# 冲突硬校验:与任何其他源的时间(或自身多个时间)间隔不足全局最小间隔 → 拒绝保存(不弹窗,直接拦)
plan_gap = 40
try:
plan_gap = int(json.loads((Path(pl.default_conf_dir(pl.default_work_dir())) /
"schedule-plan.json").read_text(encoding="utf-8")
).get("min_gap_min", 40))
except (OSError, ValueError, TypeError):
pass
def _mins(t):
h, m = t.split(":")
return int(h) * 60 + int(m)
def _circ_diff(a, b): # 24h 回绕(23:55 与 00:05 相差 10 分钟)
d = abs(a - b) % 1440
return min(d, 1440 - d)
others = []
for other in pl.list_schedules():
if other == name:
continue
others += [(other, x.strip()) for x in pl.schedule_times(other).split(",") if x.strip()]
new_mins = [_mins(t) for t in times]
conflicts = []
for t, tm in zip(times, new_mins):
conflicts += [f"{t} 与 {oname} 的 {ot} 间隔不足 {plan_gap} 分钟"
for oname, ot in others if _circ_diff(tm, _mins(ot)) < plan_gap]
for i in range(len(new_mins)):
for j in range(i + 1, len(new_mins)):
if _circ_diff(new_mins[i], new_mins[j]) < plan_gap:
conflicts.append(f"{times[i]} 与 {times[j]} 自身间隔不足 {plan_gap} 分钟")
if conflicts:
flash("保存被拒绝,时间冲突:\n- " + "\n- ".join(dict.fromkeys(conflicts[:8]))
+ f"\n(全局最小间隔 {plan_gap} 分钟)", "error")
return redirect(url_for("schedule_board"))
joined = ",".join(times)
rc, out, err = pl.call("nh_schedule_write", name, joined, timeout=60)
if rc != 0:
......
......@@ -179,6 +179,15 @@ function toggleEdit(name) {
<button type="button" class="btn" onclick="toggleEdit('{{ r.name }}')">收起</button>
</div>
</form>
<form method="POST" action="{{ url_for('schedule_time_set') }}" class="drow"
style="margin-top:14px;border-top:1px dashed #2a2d37;padding-top:12px">
<span class="dlabel">手动时间</span>
<input type="hidden" name="name" value="{{ r.name }}">
<input type="text" name="times" value="{{ r.times|join(', ') }}" placeholder="如 05:00,17:00"
style="width:190px;background:#1a1d27;border:1px solid #2a2d37;border-radius:4px;color:#d4d4d4;padding:3px 8px;font-family:monospace">
<button type="submit" class="btn btn-sm">保存时间</button>
<span class="dnote">直接指定 HH:MM;与其他源(或自身多次)间隔不足全局最小间隔时,保存被拒绝</span>
</form>
</div>
</td>
</tr>
......
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