第二期:企业信任风 UI + 打卡科目分类 + 英语语法学习模块

- 全站按 Corporate Trust 设计规范重做:靛蓝/紫罗兰渐变、Plus Jakarta Sans
  自托管字体、带色阴影、卡片悬浮、氛围光斑
- 打卡任务增加科目分类(语文/数学/英语/运动/其他),孩子端按科目分组
- 英语语法自学模块:线性解锁课程 + 课后/周/月测验引擎,测验达标
  自动联动当日英语打卡;家长概览显示语法进度
- 课程内容:A1→B1 完整大纲,9 周 54 课 + 9 周测 + 2 月测,讲解/例句/
  练习/测验均原创,仅参考两份语法书的主题编排

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
jacobxu666
2026-08-03 01:20:04 +08:00
co-authored by Claude Opus 4.8
parent b08f6649be
commit 6ed4d5a61e
45 changed files with 5824 additions and 92 deletions
+4
View File
@@ -6,6 +6,7 @@ import { revalidatePath } from "next/cache";
import { z } from "zod";
import { db } from "@/db";
import { activationCodes, sessions, taskInstances, taskTemplates, users } from "@/db/schema";
import { SUBJECT_VALUES } from "@/db/schema";
import { todayStr } from "@/lib/dates";
import { getSessionUser } from "@/lib/auth";
@@ -76,6 +77,7 @@ export async function makeupTask(instanceId: number, done: boolean) {
const templateSchema = z.object({
childId: z.coerce.number().int().positive(),
dow: z.coerce.number().int().min(0).max(6),
subject: z.enum(SUBJECT_VALUES).catch("other"),
title: z.string().trim().min(1, "任务内容不能为空").max(100, "最多 100 字"),
requiresPhoto: z.boolean(),
});
@@ -97,6 +99,7 @@ export async function addTemplate(formData: FormData) {
const parsed = templateSchema.safeParse({
childId: formData.get("childId"),
dow: formData.get("dow"),
subject: formData.get("subject"),
title: formData.get("title"),
requiresPhoto: formData.get("requiresPhoto") === "on",
});
@@ -116,6 +119,7 @@ export async function addTemplate(formData: FormData) {
await db.insert(taskTemplates).values({
childUserId: parsed.data.childId,
dow: parsed.data.dow,
subject: parsed.data.subject,
title: parsed.data.title,
requiresPhoto: parsed.data.requiresPhoto,
sortOrder: maxRow.maxSort + 1,