From 5c33805284f85e7dc8763c61081c8e2b662aacae Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=8C=97=E6=9E=B3?=
<7854742+wang_rumeng@user.noreply.gitee.com>
Date: Fri, 17 Oct 2025 21:00:14 +0800
Subject: [PATCH] PortraitAnimeSelector
---
.../create-video/CreateInput/ConfigPanel.tsx | 13 +-
.../CreateInput/PortraitAnimeSelector.tsx | 130 ++++++++++++++++++
.../pages/create-video/CreateInput/README.md | 28 +++-
.../CreateInput/VideoCreationForm.tsx | 2 +-
.../CreateInput/config-options.ts | 5 +
.../pages/create-video/CreateInput/index.ts | 1 +
6 files changed, 169 insertions(+), 10 deletions(-)
create mode 100644 components/pages/create-video/CreateInput/PortraitAnimeSelector.tsx
diff --git a/components/pages/create-video/CreateInput/ConfigPanel.tsx b/components/pages/create-video/CreateInput/ConfigPanel.tsx
index 7a949d8..aba5505 100644
--- a/components/pages/create-video/CreateInput/ConfigPanel.tsx
+++ b/components/pages/create-video/CreateInput/ConfigPanel.tsx
@@ -3,14 +3,13 @@
import {
GlobalOutlined,
ClockCircleOutlined,
- DownOutlined,
- MobileOutlined,
- DesktopOutlined,
+ DownOutlined
} from '@ant-design/icons';
import { WandSparkles, RectangleHorizontal, RectangleVertical } from 'lucide-react';
import { Dropdown, Menu, Tooltip } from 'antd';
import { LanguageOptions, VideoDurationOptions } from './config-options';
import type { ConfigOptions, LanguageValue, VideoDurationValue } from './config-options';
+import { PortraitAnimeSelector } from './PortraitAnimeSelector';
interface ConfigPanelProps {
/** Current configuration options */
@@ -115,7 +114,7 @@ export const ConfigPanel = ({
{/* Aspect ratio toggles */}
-
+
+
+ {/* Portrait/Anime selector */}
+
onConfigChange('pcode', v)}
+ />
);
};
diff --git a/components/pages/create-video/CreateInput/PortraitAnimeSelector.tsx b/components/pages/create-video/CreateInput/PortraitAnimeSelector.tsx
new file mode 100644
index 0000000..ce5bfe4
--- /dev/null
+++ b/components/pages/create-video/CreateInput/PortraitAnimeSelector.tsx
@@ -0,0 +1,130 @@
+"use client";
+
+import React, { useEffect, useMemo, useState } from 'react';
+import { Dropdown, Menu } from 'antd';
+import { DownOutlined } from '@ant-design/icons';
+import { fetchSettingByCode } from '@/api/serversetting';
+import type { PortraitAnimeValue } from './config-options';
+
+interface PortraitAnimeSelectorProps {
+ /** Current value: 'portrait' or anime pcode */
+ value: PortraitAnimeValue;
+ /** Change handler */
+ onChange: (value: PortraitAnimeValue) => void;
+ /** Optional class name */
+ className?: string;
+ /** Disabled state */
+ disabled?: boolean;
+}
+
+/**
+ * Portrait/Anime selector with dropdown for Anime subtypes.
+ * Styled to match VideoCreationForm design.
+ * @param {PortraitAnimeValue} value - Current value: 'portrait' or anime pcode
+ * @param {(value: PortraitAnimeValue) => void} onChange - Change handler
+ * @param {string} [className] - Optional wrapper class
+ * @param {boolean} [disabled] - Disable interaction when true
+ * @returns {JSX.Element}
+ */
+export function PortraitAnimeSelector({
+ value,
+ onChange,
+ className,
+ disabled = false,
+}: PortraitAnimeSelectorProps) {
+ const [lastAnimeChoice, setLastAnimeChoice] = useState('STANDARD_V1_734684_116483');
+ const [animeOptions, setAnimeOptions] = useState>([]);
+
+ useEffect(() => {
+ if (value && value !== 'portrait') {
+ setLastAnimeChoice(value);
+ }
+ }, [value]);
+
+ useEffect(() => {
+ let mounted = true;
+ (async () => {
+ const list = await fetchSettingByCode>('comic_config', []);
+ if (!mounted) return;
+ if (Array.isArray(list) && list.length > 0) {
+ setAnimeOptions(list);
+ setLastAnimeChoice((prev) => (prev === 'STANDARD_V1_734684_116483' ? list[0].pcode : prev));
+ } else {
+ setAnimeOptions([
+ { name: 'Korean Comics Long', pcode: 'STANDARD_V1_734684_116483' },
+ ]);
+ }
+ })();
+ return () => { mounted = false; };
+ }, []);
+
+ const isPortrait = value === 'portrait';
+ const currentAnime = useMemo(() => (value && value !== 'portrait' ? value : lastAnimeChoice), [value, lastAnimeChoice]);
+ const pcodeToName = useMemo(() => {
+ const map: Record = {};
+ animeOptions.forEach((o) => { map[o.pcode] = o.name; });
+ return map;
+ }, [animeOptions]);
+
+ /** Anime dropdown menu */
+ const animeMenu = (
+