From 39d82bdf0395365095885d1a1160f6fc88750693 Mon Sep 17 00:00:00 2001 From: huangmin <2927933426@qq.com> Date: Thu, 4 Jun 2026 15:15:58 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E7=AB=99=E7=82=B9?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E7=B3=BB=E7=BB=9F=EF=BC=8C=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=AE=A2=E6=9C=8D=E4=BA=8C=E7=BB=B4=E7=A0=81=E5=BC=B9=E7=AA=97?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 定义了ContentConfig和SystemConfig类型以及ConfigResponse响应类型 2. 重构HeaderIconButton组件支持透传属性 3. 新增获取站点配置接口调用逻辑 4. 给微信客服按钮添加二维码弹窗展示功能 --- src/app/api/config/route.ts | 76 +++++++++++++++++++++++++++++++++++++ src/app/page.tsx | 59 ++++++++++++++++++++-------- 2 files changed, 120 insertions(+), 15 deletions(-) diff --git a/src/app/api/config/route.ts b/src/app/api/config/route.ts index 159c5fe7..720ec246 100644 --- a/src/app/api/config/route.ts +++ b/src/app/api/config/route.ts @@ -1,7 +1,83 @@ import { NextRequest, NextResponse } from "next/server"; import { requireLogin } from "@/app/api/_auth"; const UPSTREAM_CONFIG_PATH = "/api_client/param/config"; +type ContentConfig = { + indexMainSlogan: string; + indexSubSlogan: string; + indexBannerImage: string; + exploreHeaderImage: string; + exploreHeaderTitle: string; + subscribeHeaderImage: string; + subscribeHeaderTitle: string; + userHomepageHeaderImage: string; +}; + +type SystemConfig = { + serviceEmail: string; + servicePhone: string; + contactUsPageUrl: string; + useNoticePageUrl: string; + paymentTermsPageUrl: string; + copyRightRulesPageUrl: string; + customCharacterPageUrl: string; + usageTutorialPageUrl: string; + serviceQrCode: string; + wxFollowReplyMsg: string; + wxLoginReplyMsg: string; + wxRegisterReplyMsg: string; + genImageBatchSize: number; + genImageTaskRunningSize: number; + genVideoTaskRunningSize: number; + genAudioTaskRunningSize: number; + aiExpandSystemPrompt: string; + defaultBaseModelType: string; + characterLoraStrength: number; + styleLoraStrength: number; + enableMemberSubscription: boolean; + nonMemberGenImageLimitPerDay: number; + nonMemberGenVideoLimitPerDay: number; + nonMemberGenVoiceLimitPerDay: number; + nonMemberTaskQueueSize: number; + basicMemberTaskQueueSize: number; + standardMemberTaskQueueSize: number; + seniorMemberTaskQueueSize: number; + futureCreatorMemberTaskQueueSize: number; + sdImageGenerationCoinPrice: number; + hdImageGenerationCoinPrice: number; + sdImageOptimizeCoinPrice: number; + hdImageOptimizeCoinPrice: number; + sdVideoGenerationCoinPrice: number; + hdVideoGenerationCoinPrice: number; + audioGenerationCoinPrice: number; + watermarkText: string; + waterMarkFontSize: number; + videoPowerPerSecond: number; + audioPowerPerSecond: number; + trainPowerPerAvatar: number; + trainPowerPerSpeaker: number; + avatarLimitPerUser: number; + speakerLimitPerUser: number; + userJoinActivityNum: number; + activityGenImageTaskSize: number; + storyAgentPromptShow: boolean; + inviteCodeUseNumLimit: number; + inviteCodeGenerateNumUserPer: number; + genImageTimeLimit: number; + genVideoTimeLimit: number; + genAudioTimeLimit: number; + popiartStudioWindowsDownloadLink: string; + popiartStudioMacMDownloadLink: string; + popiartStudioMacInDownloadLink: string; + popiartEvidencePreservationAgreement: string; + aliyunRishDetectionConfidence: number; +}; +export type ConfigResponse = { + contentConfig?: ContentConfig; + systemConfig?: SystemConfig; + status?: string; + message?: string; +}; const getUpstreamUrl = (request: NextRequest): string => { const baseUrl = process.env.POPIART_API_BASE_URL || diff --git a/src/app/page.tsx b/src/app/page.tsx index 5be68993..1bf21ed8 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,7 +1,14 @@ "use client"; import Link from "next/link"; -import { useMemo, useEffect, useState, type ReactNode } from "react"; -import { Dropdown, type MenuProps } from "antd"; +import { + forwardRef, + useMemo, + useEffect, + useState, + type ButtonHTMLAttributes, + type ReactNode, +} from "react"; +import { Dropdown, Popover, QRCode, type MenuProps } from "antd"; import { HomeProjectsContent } from "@/components/HomeProjectsContent"; import { authFetch } from "@/utils/authFetch"; import { useUserStore } from "@/store/userStore"; @@ -13,6 +20,7 @@ import { WeChatIcon, SparklingIcon, } from "@/components/icons"; +import { ConfigResponse } from "./api/config/route"; type HeroCardData = { title: string; @@ -94,29 +102,30 @@ function DiamondLogo({ label }: { label: string }) { ); } -function HeaderIconButton({ - children, - label, -}: { +const HeaderIconButton = forwardRef & { children: ReactNode; label: string; -}) { +}>( + function HeaderIconButton({ children, label, className = "", type = "button", ...buttonProps }, ref) { return ( ); -} +}); function Header() { const [showBanner, setShowBanner] = useState(true); const { userInfo } = useUserStore(); const { language, setLanguage, t } = useI18n(); + const [systemConfig, setSystemConfig] = useState(); const languageMenuItems: MenuProps["items"] = useMemo( () => @@ -130,6 +139,19 @@ function Header() { })), [language], ); + useEffect(() => { + const fetchConfig = async () => { + const response = await authFetch(`/api/config`, { + method: "GET", + }); + if (!response.ok) return; + const result = (await response.json()) as ConfigResponse; + console.log(result); + + setSystemConfig(result.systemConfig); + }; + fetchConfig(); + }, []) return (
@@ -201,9 +223,16 @@ function Header() {
- - - + + + 扫码联系客服 +
+ }> + + + +