Google Apps Script (GAS) + Vue.js 3 で構築するマルチテナント型学習支援Webアプリ。
Firestoreをデータベースとして使用し、教育委員会 → 学校 → 教員/生徒 の階層構造で管理する。
| レイヤー | 技術 | 備考 |
|---|---|---|
| バックエンド | Google Apps Script | doGet + google.script.run |
| フロントエンド | Vue.js 3 (CDN) | SFC不使用、Options/Composition API混在 |
| DB | Firestore (REST API) | ScriptApp.getOAuthToken()で認証 |
| AI | Claude API | Sonnet 4 / Vision対応 |
| ホスティング | GAS Webアプリ | doGet でHTML配信 |
各画面のUIを確認できます(バックエンド未接続のためデータ取得は動作しません)
index.html 生徒向け画面dashboard.html 教員ダッシュボードstudent_chat.html AIチャットteacher_assist.html AI教材生成grading.html AI答案採点02_Router.gs doGet + アクションルーター01_Auth.gs 4段階ロール認証03_StudentHandler.gs 生徒向け処理04_TeacherHandler.gs 教員向け処理05-09 AI連携・匿名化・採点10_Firestore.gs REST APIクライアント06_ClaudeAI.gs API基盤07_StudentChat.gs ヒント段階制御08_TeacherAssist.gs 教材/テスト/指導案生成09_Grading.gs Vision採点| action パラメータ | 返すHTML | 用途 |
|---|---|---|
index (デフォルト) | index.html | 生徒向け画面 |
dashboard | dashboard.html | 教員ダッシュボード |
studentChat | student_chat.html | AIチャット |
teacherAssist | teacher_assist.html | AI教材生成 |
grading | grading.html | AI答案採点 |
| 関数名 | 引数 | 戻り値 |
|---|---|---|
getBoards() | - | [{ id, name }] |
getSchools(boardId) | boardId | [{ id, name }] |
loginStudent(boardId, schoolId, studentId) | 3引数 | { ok, role, boardId, schoolId, studentId, subjects } |
loginTeacher(boardId, schoolId, teacherId, pw) | 4引数 | { ok, role, boardId, schoolId, teacherId, subjects } |
loginBoardAdmin(boardId, pw) | 2引数 | { ok, role, boardId, schools } |
{ action, boardId, schoolId, studentId }| action | 追加パラメータ | 処理関数 | 説明 |
|---|---|---|---|
getMaterials | subject?, grade?, unit? | getStudentMaterials | 教材一覧(公開+履修教科のみ) |
getQuiz | quizId | getStudentQuiz | 小テスト取得(正解なし) |
submitQuizAnswer | quizId, answers[] | submitQuizAnswer | テスト回答提出(正解付きで返す) |
submitReflection | materialId, subject, answers{} | submitReflection | 振り返り提出 |
getMyKartes | - | getStudentKartes | 自分のAIカルテ一覧 |
studentChat | subject, unit, messages[], hintLevel | handleStudentChat | AIチャット |
{ action, boardId, schoolId, teacherId, teacherPassword }| action | 権限 | 処理関数 | 説明 |
|---|---|---|---|
getMaterials | teacher+ | getTeacherMaterials | 教材一覧(非公開含む) |
getReflections | teacher+ | getTeacherReflections | 振り返り一覧 |
getStudentDetail | teacher+ | getTeacherStudentDetail | 生徒詳細 |
getStudentIds | teacher+ | getTeacherStudentIds | 管理番号一覧 |
exportForAI | teacher+ | exportAnonymized | AI匿名化エクスポート |
saveMaterial | teacher+ | saveMaterial | 教材保存 |
saveQuiz | teacher+ | saveQuiz | テスト保存 |
togglePublish | teacher+ | togglePublish | 公開切替 |
importAIKarte | teacher+ | importAIKarte | カルテインポート |
saveSettings | teacher+ | saveSettings | 教科マスター保存 |
registerStudents | schoolAdmin+ | registerStudents | 生徒一括登録 |
registerTeacher | schoolAdmin+ | registerTeacher | 教員登録 |
getTeachers | schoolAdmin+ | getTeacherList | 教員一覧 |
generateMaterial | teacher+ | handleGenerateMaterial | AI教材生成 |
generateQuiz | teacher+ | handleGenerateQuiz | AIテスト生成 |
generateLesson | teacher+ | handleGenerateLesson | AI指導案生成 |
gradeAnswer | teacher+ | handleGradeAnswer | AI答案採点 |
{ action, boardId, boardPassword }| action | 処理関数 | 説明 |
|---|---|---|
getSchools | getSchools | 学校一覧 |
addSchool | addSchool | 学校追加 |
getReflections | getBoardReflections | 全学校の振り返り |
getSchoolSummary | getSchoolSummary | 学校サマリー |
| 定数 | 値 | パスヘルパー |
|---|---|---|
CONFIG.COL.BOARDS | 'boards' | - |
CONFIG.COL.SCHOOLS | 'schools' | schoolPath(boardId, schoolId) |
CONFIG.COL.STUDENTS | 'students' | schoolCol(boardId, schoolId, 'students') |
CONFIG.COL.TEACHERS | 'teachers' | 同上 |
CONFIG.COL.MATERIALS | 'materials' | 同上 |
CONFIG.COL.QUIZZES | 'quizzes' | 同上 |
CONFIG.COL.QUIZ_ANS | 'quizAnswers' | 同上 |
CONFIG.COL.REFLECTIONS | 'reflections' | 同上 |
CONFIG.COL.KARTES | 'kartes' | 同上 |
CONFIG.COL.DUMMY_MAP | 'dummyMap' | 同上 |
CONFIG.COL.GRADING | 'gradingResults' | 同上 |
| 関数 | 用途 | 例 |
|---|---|---|
fsGet(path) | 1ドキュメント取得 | fsGet('boards/b1/schools/s1/students/S001') |
fsSet(colPath, docId, data) | ID指定で作成/上書き | fsSet('boards/b1/schools/s1/students', 'S001', {...}) |
fsAdd(colPath, data) | ID自動生成で作成 | fsAdd('boards/b1/schools/s1/reflections', {...}) |
fsUpdate(path, data) | 部分更新 | fsUpdate('boards/b1/.../materials/m1', { published: true }) |
fsDelete(path) | 削除 | fsDelete('boards/b1/.../students/S001') |
fsList(colPath) | 全ドキュメント取得 | fsList('boards/b1/schools/s1/students') |
fsQuery(colPath, where, orderBy, dir, limit) | 条件付き検索 | fsQuery(col, [{field:'subject', op:'EQUAL', value:'数学'}]) |
| ロール | 定数 | 認証方法 | 権限範囲 |
|---|---|---|---|
| 生徒 | student |
管理番号の存在チェック | 自分の履修教科の教材・テスト・振り返り |
| 教科担当 | teacher |
教員ID + パスワード | 担当教科のみ(教材CRUD、振り返り閲覧、AI連携) |
| 学校管理者 | schoolAdmin |
教員ID + パスワード (role: schoolAdmin) | 全教科 + 教員管理 + 生徒管理 |
| 教育委員会 | boardAdmin |
教育委員会ID + パスワード | 学校横断閲覧 + 学校追加 |
| 関数 | チェック内容 |
|---|---|
canAccessSubject(auth, subject) | 教科担当は自教科のみ、schoolAdmin/boardAdminは全教科OK |
isTeacherOrAbove(auth) | teacher, schoolAdmin, boardAdmin のいずれか |
isSchoolAdminOrAbove(auth) | schoolAdmin, boardAdmin のいずれか |
| ファイル | 種別 | 責務 | 依存先 |
|---|---|---|---|
00_Config.gs | GS | Firebase設定・コレクションパス・ロール定数 | - |
01_Auth.gs | GS | 4段階ロール認証 + アクセスログ | 10_Firestore |
02_Router.gs | GS | doGet + handleStudentAction / handleTeacherAction / handleBoardAction | 01_Auth, 03-09 |
03_StudentHandler.gs | GS | 教材取得・テスト受験・振り返り提出・カルテ閲覧 | 10_Firestore |
04_TeacherHandler.gs | GS | 教材CRUD・振り返り閲覧・生徒詳細・教員管理・設定 | 10_Firestore, 01_Auth |
05_AnonymizeAI.gs | GS | 振り返りのダミーID匿名化エクスポート | 10_Firestore, 01_Auth |
06_ClaudeAI.gs | GS | Claude API呼び出し基盤(テキスト/Vision) | - |
07_StudentChat.gs | GS | ヒント段階制御AIチャット | 06_ClaudeAI |
08_TeacherAssist.gs | GS | AI教材/テスト/指導案生成 | 06_ClaudeAI |
09_Grading.gs | GS | AI答案採点 + 採点結果保存 | 06_ClaudeAI, 10_Firestore |
10_Firestore.gs | GS | Firestore REST APIクライアント(CRUD + Query) | 00_Config |
index.html | HTML | 生徒向け画面(ログイン・教材・テスト・振り返り) | 02_Router |
dashboard.html | HTML | 教員ダッシュボード(管理・AI連携) | 02_Router |
student_chat.html | HTML | 生徒AIチャット画面 | 02_Router |
teacher_assist.html | HTML | 教員AI生成画面(教材/テスト/指導案) | 02_Router |
grading.html | HTML | AI答案採点画面 | 02_Router |
00_Config.gs の FIREBASE_PROJECT_ID を設定| パラメータ | 用途 | 使用ページ |
|---|---|---|
action | doGetルーティング | 全ページ |
boardId | 教育委員会ID | student_chat, teacher_assist, grading |
schoolId | 学校ID | 同上 |
studentId | 管理番号 | student_chat |
teacherId | 教員ID | teacher_assist, grading |
tp | 教員パスワード | teacher_assist, grading |
google.script.run でCSVデータを送信しない。canAccessSubject() で制御。| 項目 | 規約 |
|---|---|
| GAS関数名 | camelCase: getStudentMaterials, handleTeacherAction |
| プライベート関数 | _プレフィックス: _fsHeaders(), _writeLog() |
| Firestore操作 | 必ず 10_Firestore.gs のヘルパーを使う(直接REST呼び出し禁止) |
| 認証チェック | Router内で authenticate* を呼ぶ。Handler側では呼ばない。 |
| パスヘルパー | schoolPath(), schoolCol() を使う(パス文字列を直書きしない) |
| フロントエンド → GAS | gas(fnName, ...args) ヘルパー経由。直接 google.script.run を使わない。 |
| エラーハンドリング | GAS側は throw new Error()、フロント側は try/catch + showToast |
?tp=... で開かれる。
GAS WebアプリはHTTPS + Google認証基盤上で動作するため許容しているが、将来的にはセッショントークン方式への移行を検討。