- Add admin/lesson-plans, parent/lesson-plans, student/lesson-plans routes - Add student/practice and teacher/practice routes for adaptive practice - Add management/grade/dashboard and management/grade/practice routes - Add teacher/lesson-plans error and loading boundaries - Update existing admin, parent, student, teacher pages with new features - Update globals.css and proxy middleware
54 lines
2.0 KiB
TypeScript
54 lines
2.0 KiB
TypeScript
import type { Metadata } from "next"
|
||
import type { JSX } from "react"
|
||
import { getTranslations } from "next-intl/server"
|
||
|
||
import { requirePermission } from "@/shared/lib/auth-guard"
|
||
import { Permissions } from "@/shared/types/permissions"
|
||
import { AiProviderSettingsCard } from "@/modules/settings/components/ai-provider-settings-card"
|
||
import { AiUsageDashboard } from "@/modules/ai/components/ai-usage-dashboard"
|
||
|
||
export async function generateMetadata(): Promise<Metadata> {
|
||
const t = await getTranslations("ai")
|
||
return {
|
||
title: `${t("admin.settings.title")} - Next_Edu`,
|
||
description: t("admin.settings.description"),
|
||
}
|
||
}
|
||
|
||
export const dynamic = "force-dynamic"
|
||
|
||
/**
|
||
* AI 统一配置页
|
||
*
|
||
* 作为 AI 模块的独立配置入口,取代:
|
||
* - /settings?tab=ai(已移除 AI 标签页)
|
||
* - 考试页面内嵌的 AI 配置弹窗(已移除)
|
||
*
|
||
* 权限规则:
|
||
* - AI_CHAT 用户均可访问(管理自己的 private provider)
|
||
* - AI_CONFIGURE 用户(管理员)可额外管理 public provider 与他人 private provider
|
||
*/
|
||
export default async function AiSettingsPage(): Promise<JSX.Element> {
|
||
const t = await getTranslations("ai")
|
||
const ctx = await requirePermission(Permissions.AI_CHAT)
|
||
const isAdmin = ctx.permissions.includes(Permissions.AI_CONFIGURE)
|
||
return (
|
||
<div className="flex h-full flex-col gap-8 p-8">
|
||
<div className="flex flex-col justify-between gap-4 md:flex-row md:items-center">
|
||
<div className="space-y-1">
|
||
<h1 className="text-3xl font-bold tracking-tight">{t("admin.settings.title")}</h1>
|
||
<div className="text-sm text-muted-foreground">
|
||
{isAdmin
|
||
? t("admin.settings.description")
|
||
: t("admin.settings.userDescription")}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div className="space-y-6">
|
||
<AiProviderSettingsCard isAdmin={isAdmin} currentUserId={ctx.userId} />
|
||
{isAdmin ? <AiUsageDashboard /> : null}
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|