File size: 12,165 Bytes
0725350
b7fa969
37ea22f
 
 
b7fa969
cbd13dc
b7fa969
 
cbd13dc
 
 
d3b98cb
cbd13dc
 
0725350
cbd13dc
 
d3b98cb
cbd13dc
37ea22f
cbd13dc
37ea22f
 
b7fa969
 
cbd13dc
d3b98cb
 
 
cbd13dc
 
b7fa969
cbd13dc
 
 
 
 
 
 
 
 
b7fa969
37ea22f
cbd13dc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37ea22f
cbd13dc
 
 
 
d3b98cb
cbd13dc
 
 
d3b98cb
 
 
 
0725350
d3b98cb
 
 
0725350
d3b98cb
 
 
0725350
cbd13dc
 
 
d3b98cb
0725350
d3b98cb
cbd13dc
 
 
 
 
 
d3b98cb
 
cbd13dc
 
0725350
cbd13dc
 
 
 
 
 
 
 
37ea22f
d3b98cb
 
 
 
cbd13dc
d3b98cb
 
 
 
 
 
 
cbd13dc
 
 
 
d3b98cb
 
37ea22f
d3b98cb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b7fa969
d3b98cb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cbd13dc
d3b98cb
 
37ea22f
cbd13dc
 
b7fa969
 
37ea22f
 
cbd13dc
37ea22f
cbd13dc
 
 
37ea22f
 
 
b7fa969
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
{% extends "base.html" %}
{% block title %}DRM | 后台管理{% endblock %}
{% block head %}
  <link rel="stylesheet" href="{{ url_for('static', filename='v020.css') }}">
{% endblock %}
{% block body %}
  <main class="admin-layout admin-layout-v2" data-admin-page="{{ admin_page }}">
    <section class="admin-hero card-surface">
      <div>
        <p class="section-kicker">后台管理</p>
        {% if admin_page == "schedule" %}
          <h1>时间表设置</h1>
          <p class="admin-copy">通过拖拽上课块和课间块,重新安排整套节次时间。保存后首页与周课表会自动同步。</p>
        {% elif admin_page == "lists" %}
          <h1>清单管理</h1>
          <p class="admin-copy">统一维护首页的 todolist 分类,删除或新建会即时反映到主页与拖拽池。</p>
        {% else %}
          <h1>课程管理</h1>
          <p class="admin-copy">左侧新增或编辑课程,右侧用竖直列表快速检查全周课程配置。</p>
        {% endif %}
      </div>

      <div class="action-group">
        <a class="ghost-link" href="{{ url_for('index') }}">返回主页</a>
      </div>

      <nav class="admin-page-nav" aria-label="后台分页">
        <a class="admin-page-tab {% if admin_page == 'schedule' %}is-active{% endif %}" href="{{ url_for('admin_schedule') }}">时间表设置</a>
        <a class="admin-page-tab {% if admin_page == 'lists' %}is-active{% endif %}" href="{{ url_for('admin_lists') }}">清单管理</a>
        <a class="admin-page-tab {% if admin_page == 'courses' %}is-active{% endif %}" href="{{ url_for('admin_courses') }}">课程管理</a>
      </nav>
    </section>

    {% if admin_page == "schedule" %}
      <section class="admin-section">
        <div class="admin-grid admin-grid-tight admin-schedule-grid">
          <article class="admin-card schedule-form-card">
            <div class="admin-card-head">
              <div>
                <p class="column-label">Basic Settings</p>
                <h2>基础参数</h2>
              </div>
            </div>

            <form id="scheduleSettingsForm" class="modal-form compact">
              <label>
                <span>学期开始日期</span>
                <input id="semesterStartInput" name="semester_start" type="date" value="{{ schedule_settings.semester_start }}">
              </label>
              <label>
                <span>课表显示开始</span>
                <input id="dayStartInput" name="day_start" type="time" value="{{ schedule_settings.day_start }}">
              </label>
              <label>
                <span>课表显示结束</span>
                <input id="dayEndInput" name="day_end" type="time" value="{{ schedule_settings.day_end }}">
              </label>
              <label>
                <span>默认任务时长(分钟)</span>
                <input id="defaultDurationInput" name="default_task_duration_minutes" type="number" min="30" max="240" step="15" value="{{ schedule_settings.default_task_duration_minutes }}">
              </label>
              <div class="form-actions">
                <button class="secondary-button" id="resetTimelineButton" type="button">恢复默认节次</button>
                <button class="primary-button" type="submit">保存时间表设置</button>
              </div>
            </form>
          </article>

          <article class="admin-card schedule-editor-card">
            <div class="admin-card-head">
              <div>
                <p class="column-label">Timeline Editor</p>
                <h2>拖拽块到时间轴上重新排布节次</h2>
              </div>
              <span class="task-count" id="scheduleSegmentCount">0 段</span>
            </div>

            <div class="schedule-palette" id="schedulePalette">
              <div class="schedule-palette-card class" draggable="true" data-palette-kind="class">
                <strong>上课块</strong>
                <span>拖到时间轴末尾追加一节课</span>
              </div>
              <div class="schedule-palette-card break" draggable="true" data-palette-kind="break">
                <strong>课间块</strong>
                <span>拖到时间轴末尾追加一段休息</span>
              </div>
            </div>

            <p class="admin-card-copy">规则:时间段不能重叠,上课后必须是课间,课间后必须是上课。支持拖入新块、删除节次、调整时长。</p>

            <div class="schedule-editor-shell">
              <div class="schedule-editor-axis" id="scheduleEditorAxis"></div>
              <div class="schedule-editor-track" id="scheduleEditorTrack">
                <div class="schedule-editor-dropzone" id="scheduleEditorDropzone">将上课块或课间块拖到这里,追加到时间表末尾</div>
              </div>
            </div>
          </article>
        </div>
      </section>
    {% elif admin_page == "lists" %}
      <section class="admin-section">
        <div class="admin-grid admin-grid-tight admin-lists-grid">
          <article class="admin-card create-card list-create-card">
            <div class="create-icon">+</div>
            <h2>新建一个清单</h2>
            <p class="admin-card-copy">清单会直接同步到首页与第二页的拖拽池。</p>
            <form id="createCategoryForm" class="modal-form compact">
              <label>
                <span>分类名称</span>
                <input id="newCategoryName" name="name" type="text" maxlength="20" placeholder="例如:项目推进">
              </label>
              <button class="primary-button" type="submit">立即创建</button>
            </form>
          </article>

          <section class="admin-stack list-management-stack" id="adminGrid">
            {% for category in categories %}
              <article class="admin-card admin-row-card list-row-card" data-category-id="{{ category.id }}">
                <div class="admin-row-main">
                  <div>
                    <p class="column-label">Category</p>
                    <h2>{{ category.name }}</h2>
                    <p class="admin-card-copy">删除分类会同时移除其下全部任务,请谨慎操作。</p>
                  </div>
                  <div class="admin-row-side">
                    <span class="task-count">{{ category.tasks|length }} 项任务</span>
                    <button class="danger-button" type="button" data-delete-category="{{ category.id }}">删除此清单</button>
                  </div>
                </div>
              </article>
            {% endfor %}
          </section>
        </div>
      </section>
    {% else %}
      <section class="admin-section">
        <div class="admin-grid admin-grid-tight course-management-grid">
          <article class="admin-card course-editor-card">
            <div class="admin-card-head">
              <div>
                <p class="column-label">Course Editor</p>
                <h2 id="courseEditorHeading">新增课程</h2>
              </div>
            </div>
            <p class="admin-card-copy">课程时间按“第几节到第几节”输入,系统会根据当前时间表自动换算为具体时间。</p>

            <form class="modal-form compact" id="courseForm">
              <input id="courseIdInput" name="course_id" type="hidden">
              <label>
                <span>课程名称</span>
                <input id="courseTitleInput" name="title" type="text" maxlength="40" placeholder="例如:高等数学">
              </label>
              <label>
                <span>上课地点</span>
                <input id="courseLocationInput" name="location" type="text" maxlength="40" placeholder="例如:教学楼 A302">
              </label>
              <label>
                <span>星期几</span>
                <select id="courseWeekdayInput" name="day_of_week">
                  <option value="1">星期一</option>
                  <option value="2">星期二</option>
                  <option value="3">星期三</option>
                  <option value="4">星期四</option>
                  <option value="5">星期五</option>
                  <option value="6">星期六</option>
                  <option value="7">星期日</option>
                </select>
              </label>
              <div class="split-fields">
                <label>
                  <span>开始节次</span>
                  <select id="courseStartPeriodInput" name="start_period"></select>
                </label>
                <label>
                  <span>结束节次</span>
                  <select id="courseEndPeriodInput" name="end_period"></select>
                </label>
              </div>
              <div class="split-fields">
                <label>
                  <span>开始周数</span>
                  <input id="courseStartWeekInput" name="start_week" type="number" min="1" max="30" value="1">
                </label>
                <label>
                  <span>结束周数</span>
                  <input id="courseEndWeekInput" name="end_week" type="number" min="1" max="30" value="16">
                </label>
              </div>
              <label>
                <span>单双周</span>
                <select id="courseWeekPatternInput" name="week_pattern">
                  <option value="all">每周</option>
                  <option value="odd">单周</option>
                  <option value="even">双周</option>
                </select>
              </label>
              <div class="form-actions">
                <button class="secondary-button" id="resetCourseEditorButton" type="button">清空表单</button>
                <button class="primary-button" type="submit">保存课程</button>
              </div>
            </form>
          </article>

          <section class="admin-stack course-list" id="courseGrid">
            {% if courses %}
              {% for course in courses %}
                <article class="admin-card admin-row-card course-card" data-course-id="{{ course.id }}">
                  <div class="admin-card-head course-row-head">
                    <div>
                      <p class="column-label">Course</p>
                      <h2>{{ course.title }}</h2>
                    </div>
                    <div class="course-row-actions">
                      <span class="task-count">周{{ ["一","二","三","四","五","六","日"][course.day_of_week - 1] }}</span>
                      <button class="secondary-button" type="button" data-edit-course="{{ course.id }}">编辑课程</button>
                      <button class="danger-button" type="button" data-delete-course="{{ course.id }}">删除课程</button>
                    </div>
                  </div>
                  <p class="admin-card-copy">{{ course.start_time }} - {{ course.end_time }} · 第 {{ course.start_week }}-{{ course.end_week }} 周 · {% if course.week_pattern == "odd" %}单周{% elif course.week_pattern == "even" %}双周{% else %}每周{% endif %}</p>
                  <p class="admin-card-copy">{{ course.location if course.location else "未填写地点" }}</p>
                </article>
              {% endfor %}
            {% else %}
              <article class="admin-card empty-admin-card">
                <h2>还没有固定课程</h2>
                <p class="admin-card-copy">在左侧填写课程信息并保存后,周课表会自动按周显示。</p>
              </article>
            {% endif %}
          </section>
        </div>
      </section>
    {% endif %}

    <div class="toast-stack" id="toastStack"></div>
  </main>
{% endblock %}
{% block scripts %}
  <script>
    window.__ADMIN_BOOTSTRAP__ = {
      adminPage: {{ admin_page|tojson }},
      courses: {{ courses|tojson }},
      categories: {{ categories|tojson }},
      scheduleSettings: {{ schedule_settings|tojson }},
      defaultTimeSlots: {{ default_time_slots|tojson }},
    };
  </script>
  <script src="{{ url_for('static', filename='admin-v020.js') }}"></script>
{% endblock %}