feat(ai): 统一 AI 配置入口到 /admin/ai-settings
## 新增 - 创建 /admin/ai-settings 统一配置页(AiProviderSettingsCard + AiUsageDashboard) - admin 侧边栏新增"AI 配置"菜单项(权限 AI_CONFIGURE,图标 Sparkles) - 新增 deleteAiProvider 数据访问层(事务删除 + 自动转移默认) - 新增 deleteAiProviderAction Server Action(Zod 校验 + 权限校验) - AiProviderSettingsCard 新增删除按钮(AlertDialog 确认 + destructive 变体) - 新增 i18n 翻译键(delete/deleteConfirm/deleteSuccess 等,zh-CN + en) ## 移除 - 从 /settings 移除 AI 标签页(原 VALID_TABS 含 "ai",现仅 4 标签页) - 从考试页面移除 AI 配置弹窗(Dialog + AiProviderSettingsCard 内嵌) - 从 ai-provider-selector.tsx 移除配置弹窗(managePanel/manageOpen props) - 移除 settings-view.tsx 中 canConfigureAi 逻辑和未使用 import ## 变更 - 考试页面"管理"按钮改为 Link 跳转到 /admin/ai-settings - ai-provider-selector.tsx"管理"按钮改为 Link 跳转到 /admin/ai-settings - exam-form.tsx 移除 providerDialogOpen/providerDialogKey 状态 - 修正架构文档 004 中 Action 命名(getAiProvidersAction → getAiProviderSummaries 等) ## 架构文档同步 - 004 更新 settings 模块章节(V3 标记/修正 Action 名称/新增 deleteAiProvider) - 005 新增 deleteAiProviderAction 节点 + /admin/ai-settings 路由
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
"use client"
|
||||
|
||||
import Link from "next/link"
|
||||
import { useTranslations } from "next-intl"
|
||||
import { Settings } from "lucide-react"
|
||||
import {
|
||||
@@ -17,14 +18,6 @@ import {
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/shared/components/ui/select"
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/shared/components/ui/dialog"
|
||||
import { Button } from "@/shared/components/ui/button"
|
||||
import type { Control } from "react-hook-form"
|
||||
|
||||
@@ -47,11 +40,6 @@ type AiProviderSelectorProps = {
|
||||
loading?: boolean
|
||||
/** Provider 标签映射 */
|
||||
providerLabels?: Record<string, string>
|
||||
/** 管理面板触发器 */
|
||||
managePanel?: React.ReactNode
|
||||
/** 管理面板打开状态 */
|
||||
manageOpen?: boolean
|
||||
onManageOpenChange?: (open: boolean) => void
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,6 +47,8 @@ type AiProviderSelectorProps = {
|
||||
*
|
||||
* 可复用的表单字段组件,用于选择 AI Provider。
|
||||
* 从 exam-ai-generator.tsx 抽取,支持在任何需要 AI Provider 选择的表单中复用。
|
||||
*
|
||||
* V3:移除内嵌配置弹窗,"管理"按钮改为跳转到 /admin/ai-settings 统一配置页。
|
||||
*/
|
||||
export function AiProviderSelector({
|
||||
control,
|
||||
@@ -66,9 +56,6 @@ export function AiProviderSelector({
|
||||
providers,
|
||||
loading = false,
|
||||
providerLabels,
|
||||
managePanel,
|
||||
manageOpen,
|
||||
onManageOpenChange,
|
||||
}: AiProviderSelectorProps): React.ReactNode {
|
||||
const t = useTranslations("ai")
|
||||
|
||||
@@ -80,28 +67,12 @@ export function AiProviderSelector({
|
||||
<FormItem>
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<FormLabel>{t("provider.label")}</FormLabel>
|
||||
{managePanel ? (
|
||||
<Dialog open={manageOpen} onOpenChange={onManageOpenChange}>
|
||||
<DialogTrigger asChild>
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="h-7 px-2 text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
<Settings className="mr-1 h-3.5 w-3.5" />
|
||||
{t("provider.manage")}
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="sm:max-w-[960px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>{t("provider.manageTitle")}</DialogTitle>
|
||||
<DialogDescription>{t("provider.manageDescription")}</DialogDescription>
|
||||
</DialogHeader>
|
||||
{managePanel}
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
) : null}
|
||||
<Button asChild type="button" variant="ghost" size="sm" className="h-7 px-2 text-muted-foreground hover:text-foreground">
|
||||
<Link href="/admin/ai-settings">
|
||||
<Settings className="mr-1 h-3.5 w-3.5" />
|
||||
{t("provider.manage")}
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
<Select value={field.value as string} onValueChange={field.onChange} disabled={loading}>
|
||||
<FormControl>
|
||||
|
||||
Reference in New Issue
Block a user