File size: 8,867 Bytes
7547388
 
 
 
 
 
 
 
 
5fbb440
7547388
 
 
 
 
 
 
 
 
 
 
 
dcab2e7
7547388
 
 
dcab2e7
7547388
 
 
 
 
 
 
 
 
 
 
dcab2e7
 
7547388
 
 
 
 
dcab2e7
7547388
 
 
 
 
 
 
 
 
dcab2e7
7547388
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dcab2e7
 
 
 
7547388
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dcab2e7
7547388
 
 
 
 
 
 
 
 
 
bfe0d21
7547388
 
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
<!doctype html>
<html lang="zh-Hant" class="student-page">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
  <meta name="color-scheme" content="light">
  <title>Python 專案教室|學生工作區</title>
  <link rel="stylesheet" href="/classroom-assets/vendor/codemirror/codemirror.css">
  <link rel="stylesheet" href="/classroom-assets/vendor/codemirror/material-darker.css">
  <link rel="stylesheet" href="/classroom-assets/classroom.css?v=2026fall-21">
</head>
<body>
  <header class="app-header">
    <div class="brand">
      <div class="brand-mark">Py</div>
      <div class="brand-copy">
        <strong>Python 專案教室</strong>
        <span id="studentIdentity">尚未進入教室</span>
      </div>
    </div>
    <div class="header-actions">
      <div class="connection-state"><i class="status-dot" id="connectionDot"></i><span id="connectionText">未連線</span></div>
      <button class="btn help compact" id="helpButton" aria-describedby="helpStatus">請老師協助</button>
      <button class="btn secondary compact" id="identityButton">更換身分</button>
    </div>
  </header>
  <span class="sr-only" id="helpStatus" aria-live="polite"></span>

  <section class="project-bar">
    <div class="project-context">
      <label for="weekSelect">Lesson</label><select id="weekSelect"></select>
      <label for="projectName">專案</label><input id="projectName" maxlength="36">
    </div>
    <div class="project-actions">
      <button class="copy-button" id="templateButton">匯入專案起始套版</button>
      <button class="copy-button" id="progressButton">選擇舊進度</button>
      <button class="copy-button" id="importButton">匯入 .py / ZIP</button>
      <button class="copy-button" id="exportButton">匯出專案</button>
      <button class="copy-button checkpoint-action" id="checkpointButton" title="建立一個可以從進度載回的版本,不會交給老師或發布">暫存版本</button>
      <button class="btn compact" id="submitButton" title="正式提交目前版本給老師檢查;老師另行發布後才會公開">正式提交</button>
      <input id="fileImport" type="file" accept=".py,.zip" hidden>
    </div>
  </section>

  <nav class="mobile-tabs" role="tablist">
    <button class="mobile-tab" data-panel="referencePanel">專案/任務</button>
    <button class="mobile-tab" data-panel="editorPanel" aria-selected="true">程式</button>
    <button class="mobile-tab" data-panel="consolePanel">執行結果</button>
  </nav>

  <main class="student-layout" id="studentLayout">
    <aside class="panel reference-panel" id="referencePanel">
      <div class="side-tabs">
        <button class="side-tab active" data-side="filesView">專案檔案</button>
        <button class="side-tab" data-side="syntaxView">語法查詢</button>
        <button class="side-tab" data-side="lessonView" id="lessonTab">本堂任務</button>
      </div>
      <section class="side-view" id="filesView">
        <div class="panel-heading"><h1>檔案夾</h1><button class="copy-button" id="newFileButton">+新增</button></div>
        <div class="file-list" id="fileList"></div>
        <p class="side-note">入口固定為 <code>main.py</code>,可用 <code>import</code> 引入其他 Python 檔。</p>
      </section>
      <section class="side-view" id="syntaxView" hidden>
        <div class="panel-heading"><h1>Python 語法查詢</h1><span id="snippetCount">0 項</span></div>
        <div class="search-wrap">
          <label class="field-label" for="syntaxSearch">輸入語法或用途</label>
          <input class="text-field" id="syntaxSearch" type="search">
          <div class="chip-row" id="categoryFilters"></div>
        </div>
        <div class="snippet-list" id="snippetList"></div>
      </section>
      <section class="side-view" id="lessonView" hidden>
        <div class="panel-heading"><h1 id="lessonHeading">本堂任務</h1><span id="lessonLabel"></span></div>
        <div class="lesson-guide-content" id="lessonGuideContent"></div>
      </section>
    </aside>

    <div class="panel-resizer reference-resizer" id="referenceResizer" role="separator" aria-label="調整專案側欄寬度" aria-orientation="vertical" tabindex="0" title="拖曳調整寬度;雙擊恢復預設"></div>

    <section class="panel editor-panel mobile-active" id="editorPanel">
      <div class="panel-heading dark">
        <span class="file-name" id="activeFileLabel">main.py</span>
        <div class="editor-toolbar">
          <button class="editor-toggle" id="toggleReferenceButton" aria-pressed="false">隱藏側欄</button>
          <button class="editor-toggle" id="toggleConsoleButton" aria-pressed="false">隱藏 Console</button>
          <button class="btn stop compact" id="stopButton" disabled>停止</button>
          <button class="btn compact" id="runButton" disabled>載入 Python…</button>
        </div>
      </div>
      <div class="editor-host"><textarea id="codeEditor" aria-label="程式碼"></textarea></div>
    </section>

    <div class="panel-resizer console-resizer" id="consoleResizer" role="separator" aria-label="調整 Console 寬度" aria-orientation="vertical" tabindex="0" title="拖曳調整寬度;雙擊恢復預設"></div>

    <aside class="panel console-panel" id="consolePanel">
      <div class="panel-heading"><h2>執行結果</h2><button class="copy-button" id="clearOutputButton">清除</button></div>
      <div class="console-body">
        <div class="console-tabs" id="consoleTabs" role="tablist" aria-label="執行結果檢視" hidden>
          <button class="console-tab active" id="consoleOutputTab" role="tab" aria-selected="true">文字輸出</button>
          <button class="console-tab" id="pygameOutputTab" role="tab" aria-selected="false">遊戲畫面</button>
        </div>
        <div class="console-stream" id="consoleStream" data-view="console">
          <pre class="console-output" id="consoleOutput">Python 執行環境載入中…</pre>
          <iframe id="pygameFrame" title="Pygame 遊戲畫面" sandbox="allow-scripts" hidden></iframe>
          <form class="console-input-row" id="consoleInputForm" hidden>
            <span aria-hidden="true">›</span>
            <label class="sr-only" for="consoleInput">Python 程式要求輸入</label>
            <input id="consoleInput" autocomplete="off">
            <button class="btn compact" type="submit">送出</button>
          </form>
        </div>
        <p class="console-hint" id="consoleHint">一般 Python 可使用 <code>input()</code>。Pygame 使用瀏覽器畫布,需用 <code>async main()</code> 與 <code>await asyncio.sleep()</code>;目前支援程式繪圖,不支援 <code>input()</code> 或外部圖片/音效檔。範例請在語法查詢搜尋 Pygame。</p>
        <div class="console-status">
          <i class="status-dot" id="runStatusDot"></i><span id="runStatusText">準備環境</span>
          <span>·</span><span id="saveStatus">尚未同步</span>
          <span>·</span><span id="submitStatus">尚未暫存或提交</span>
        </div>
      </div>
    </aside>
  </main>

  <dialog id="identityDialog">
    <form class="dialog-content form-stack" id="identityForm">
      <div><h1>進入程式教室</h1><p>選擇班級並輸入自己在名單上的姓名。</p></div>
      <div><label class="field-label" for="classCode">課程</label><select class="text-field" id="classCode" required></select></div>
      <div><label class="field-label" for="displayName">姓名</label><input class="text-field" id="displayName" autocomplete="name" required><p class="field-help">姓名必須與老師建立的名單一致。</p></div>
      <p class="form-error" id="identityError" role="alert"></p>
      <button class="btn" type="submit">進入教室</button>
    </form>
  </dialog>

  <dialog id="progressDialog">
    <div class="dialog-content">
      <h2>選擇已儲存版本</h2>
  <p>自動同步更新老師可查看的目前草稿,不會建立歷史版本;「暫存版本」建立可載回的工作版本;「正式提交」凍結一份交給老師檢查,老師另行發布後才會公開。載入舊版本只建立工作副本,不會刪除歷史紀錄。</p>
      <div class="progress-list" id="progressList"></div>
      <button class="btn secondary dialog-close">關閉</button>
    </div>
  </dialog>
  <div class="toast" id="toast"></div>

  <script src="/classroom-assets/vendor/codemirror/codemirror.js"></script>
  <script src="/classroom-assets/vendor/codemirror/python.js"></script>
  <script src="/classroom-assets/vendor/jszip/jszip.min.js"></script>
  <script src="/classroom-assets/pygame-support.js?v=2026fall-1"></script>
  <script src="/classroom-assets/student.js?v=2026fall-20"></script>
</body>
</html>