| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- <!doctype html>
- <html lang="zh-CN">
- <head>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <title><%= title %></title>
- <link rel="stylesheet" href="/styles.css">
- </head>
- <body>
- <%- include('partials/nav') %>
- <%
- const scheduleNextOccurrence = typeof nextOccurrence !== 'undefined' ? nextOccurrence : null;
- const scheduleThisWeek = typeof thisWeek !== 'undefined' && Array.isArray(thisWeek) ? thisWeek : [];
- const scheduleNextWeek = typeof nextWeek !== 'undefined' && Array.isArray(nextWeek) ? nextWeek : [];
- %>
- <main>
- <section class="hero tile-light compact page-intro">
- <p class="eyebrow">Schedule</p>
- <h1>定时计划</h1>
- <p class="lead">支持每天、工作日、法定工作日、自定义。</p>
- <div class="hero-actions compact-actions">
- <button class="button-primary" type="button" id="openScheduleDialog">添加计划</button>
- </div>
- </section>
- <% if (message) { %><div class="notice"><%= message %></div><% } %>
- <% if (error) { %><div class="notice notice-error"><%= error %></div><% } %>
- <section class="tile-parchment compact">
- <div class="section-heading dark-text">
- <h2>本周与下周计划</h2>
- <p>
- <% if (scheduleNextOccurrence) { %>
- 下一次:<%= actionLabel(scheduleNextOccurrence.action) %>,<%= scheduleNextOccurrence.at %>。
- <% } else { %>
- 暂无后续计划。
- <% } %>
- </p>
- </div>
- <div class="plan-columns">
- <%- include('partials/occurrences', { title: '本周计划', items: scheduleThisWeek }) %>
- <%- include('partials/occurrences', { title: '下周计划', items: scheduleNextWeek }) %>
- </div>
- </section>
- <section class="tile-light compact">
- <div class="card-grid">
- <% schedules.forEach((item) => { %>
- <article class="utility-card schedule-card <%= item.is_enabled ? '' : 'schedule-disabled' %>" data-schedule-card data-id="<%= item.id %>" data-name="<%= item.name %>" data-target-channel="<%= item.target_channel %>" data-action="<%= item.action %>" data-time="<%= item.time %>" data-repeat-type="<%= item.repeat_type %>" data-weekdays="<%= item.weekdays %>">
- <p class="eyebrow schedule-status <%= item.is_enabled ? 'schedule-status-enabled' : 'schedule-status-disabled' %>"><%= item.is_enabled ? '启用' : '停用' %></p>
- <div class="schedule-content">
- <h3><%= item.name %></h3>
- <p><%= item.time %> · <%= actionLabel(item.action) %> · <%= targetLabel(item.target_channel) %></p>
- <p><%= repeatLabel(item.repeat_type) %><% if (item.weekdays) { %>:<%= item.weekdays.split(',').map(weekdayLabel).join('、') %><% } %></p>
- </div>
- <div class="inline-actions">
- <button class="button-secondary small" type="button" data-edit-schedule>修改</button>
- <form method="post" action="/schedules/<%= item.id %>/toggle"><button class="button-secondary small"><%= item.is_enabled ? '停用' : '启用' %></button></form>
- <form method="post" action="/schedules/<%= item.id %>/delete"><button class="button-secondary small">删除</button></form>
- </div>
- </article>
- <% }) %>
- </div>
- </section>
- </main>
- <dialog class="modal" id="scheduleDialog">
- <div class="modal-header">
- <div>
- <p class="eyebrow">Schedule</p>
- <h2 id="scheduleDialogTitle">添加计划</h2>
- </div>
- <button class="modal-close" type="button" id="closeScheduleDialog" aria-label="关闭">×</button>
- </div>
- <form method="post" action="/schedules" class="form-grid modal-form" id="scheduleForm">
- <label>名称<input name="name" required placeholder="例如 工作日开灯"></label>
- <label>目标
- <select name="target_channel">
- <option value="0">全部灯</option>
- <option value="1">灯1</option>
- <option value="2">灯2</option>
- <option value="3">灯3</option>
- </select>
- </label>
- <label>动作
- <select name="action">
- <option value="open">开灯</option>
- <option value="close">关灯</option>
- </select>
- </label>
- <label>时间<input name="time" type="text" inputmode="numeric" pattern="([01][0-9]|2[0-3]):[0-5][0-9]" placeholder="24 小时制 HH:mm,例如 09:00、18:30" required></label>
- <label>重复
- <select name="repeat_type" id="repeatType">
- <option value="daily">每天</option>
- <option value="workday">工作日</option>
- <option value="holiday">法定工作日</option>
- <option value="custom">自定义</option>
- </select>
- </label>
- <div class="weekday-picker" id="weekdayPicker" hidden>
- <% [1,2,3,4,5,6,7].forEach((day) => { %>
- <label><input type="checkbox" name="weekdays" value="<%= day %>"> 周<%= weekdayLabel(day) %></label>
- <% }) %>
- </div>
- <div class="modal-actions">
- <button class="button-secondary" type="button" id="cancelScheduleDialog">取消</button>
- <button class="button-primary" id="scheduleSubmitButton">创建计划</button>
- </div>
- </form>
- </dialog>
- <script>
- const scheduleDialog = document.getElementById('scheduleDialog');
- const openScheduleDialog = document.getElementById('openScheduleDialog');
- const closeScheduleDialog = document.getElementById('closeScheduleDialog');
- const cancelScheduleDialog = document.getElementById('cancelScheduleDialog');
- const scheduleDialogTitle = document.getElementById('scheduleDialogTitle');
- const scheduleForm = document.getElementById('scheduleForm');
- const scheduleSubmitButton = document.getElementById('scheduleSubmitButton');
- const repeatType = document.getElementById('repeatType');
- const weekdayPicker = document.getElementById('weekdayPicker');
- function syncWeekdayPicker() {
- const isCustom = repeatType.value === 'custom';
- weekdayPicker.hidden = !isCustom;
- if (!isCustom) {
- weekdayPicker.querySelectorAll('input[type="checkbox"]').forEach((input) => {
- input.checked = false;
- });
- }
- }
- function openCreateScheduleDialog() {
- scheduleDialogTitle.textContent = '添加计划';
- scheduleSubmitButton.textContent = '创建计划';
- scheduleForm.action = '/schedules';
- scheduleForm.reset();
- syncWeekdayPicker();
- scheduleDialog.showModal();
- }
- function openEditScheduleDialog(card) {
- scheduleDialogTitle.textContent = '修改计划';
- scheduleSubmitButton.textContent = '保存修改';
- scheduleForm.action = `/schedules/${card.dataset.id}/update`;
- scheduleForm.elements.name.value = card.dataset.name || '';
- scheduleForm.elements.target_channel.value = card.dataset.targetChannel || '0';
- scheduleForm.elements.action.value = card.dataset.action || 'open';
- scheduleForm.elements.time.value = card.dataset.time || '';
- scheduleForm.elements.repeat_type.value = card.dataset.repeatType || 'daily';
- const weekdays = (card.dataset.weekdays || '').split(',').filter(Boolean);
- weekdayPicker.querySelectorAll('input[type="checkbox"]').forEach((input) => {
- input.checked = weekdays.includes(input.value);
- });
- syncWeekdayPicker();
- scheduleDialog.showModal();
- }
- openScheduleDialog.addEventListener('click', openCreateScheduleDialog);
- document.querySelectorAll('[data-edit-schedule]').forEach((button) => {
- button.addEventListener('click', () => openEditScheduleDialog(button.closest('[data-schedule-card]')));
- });
- closeScheduleDialog.addEventListener('click', () => scheduleDialog.close());
- cancelScheduleDialog.addEventListener('click', () => scheduleDialog.close());
- scheduleDialog.addEventListener('click', (event) => {
- if (event.target === scheduleDialog) scheduleDialog.close();
- });
- repeatType.addEventListener('change', syncWeekdayPicker);
- syncWeekdayPicker();
- </script>
- </body>
- </html>
|