Files
xiaoxia-saas/apps/web/src/pages/editing-planner/components/TransitionSelector.tsx
T
xiaoxia 3862996045
CI/CD Pipeline / Production Browser E2E (push) Failing after 1312h43m40s
CI/CD Pipeline / Deploy Production (push) Failing after 1312h43m42s
CI/CD Pipeline / Build Production Worker Image (push) Failing after 1312h48m16s
CI/CD Pipeline / Build Production API Image (push) Failing after 1312h48m20s
CI/CD Pipeline / PR Build Worker Image (push) Failing after 1312h49m4s
CI/CD Pipeline / Check if frontend-only change (push) Failing after 1312h51m34s
CI/CD Pipeline / PR Build API Image (push) Failing after 1312h49m8s
CI/CD Pipeline / Build Staging API Image (push) Successful in 13m4s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m5s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 4m56s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 58s
CI/CD Pipeline / Validate - Code Quality (push) Failing after 2m0s
CI/CD Pipeline / Validate - Type Check (mypy) (push) Successful in 1m5s
CI/CD Pipeline / Validate - Migration (alembic) (push) Successful in 1m12s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 21s
CI/CD Pipeline / Unit Tests (push) Successful in 6m21s
CI/CD Pipeline / Integration Tests (push) Successful in 2m38s
CI/CD Pipeline / Frontend Lint (push) Successful in 46s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 2m39s
CI/CD Pipeline / PR Build Web Image (push) Failing after 1313h21m29s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 4m40s
CI/CD Pipeline / Build Production Web Image (push) Failing after 1313h20m41s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 35s
refactor(#783): 统一API文件命名风格为kebab-case (#788)
2026-07-23 22:34:56 +08:00

116 lines
3.3 KiB
TypeScript

/**
* 转场特效选择器 — Drawer 形式
* 14 种转场预设卡片网格 + 转场时长滑块
* 支持全局默认转场 + 单个片段间独立设置
*/
import React, { useCallback } from "react"
import { Drawer, Slider } from "antd"
import { TRANSITION_OPTIONS } from "@/api/template-editor"
import type { TransitionConfig, TransitionType } from "../types"
import { DEFAULT_TRANSITION } from "../types"
/* ──────────── Props ──────────── */
interface TransitionSelectorProps {
open: boolean
onClose: () => void
/** 当前转场配置 */
config: TransitionConfig
onChange: (config: TransitionConfig) => void
/** 标题提示(区分全局 / 片段间) */
title?: string
}
const TransitionSelector: React.FC<TransitionSelectorProps> = ({
open,
onClose,
config,
onChange,
title = "转场特效",
}) => {
/* ── 选择转场类型 ── */
const handleSelectType = useCallback(
(type: TransitionType) => {
onChange({ ...config, type })
},
[config, onChange],
)
/* ── 修改时长 ── */
const handleChangeDuration = useCallback(
(duration: number) => {
onChange({ ...config, duration })
},
[config, onChange],
)
/* ── 重置为无转场 ── */
const handleReset = useCallback(() => {
onChange({ ...DEFAULT_TRANSITION })
}, [onChange])
return (
<Drawer
title={`🎬 ${title}`}
placement="right"
width={480}
open={open}
onClose={onClose}
className="transition-selector-drawer"
>
{/* ── 时长滑块 ── */}
<div className="ts-duration-section">
<div className="ts-duration-header">
<span className="ts-duration-label">转场时长</span>
<span className="ts-duration-value">{config.duration.toFixed(1)}s</span>
</div>
<Slider
min={0.3}
max={2.0}
step={0.1}
value={config.duration}
onChange={handleChangeDuration}
tooltip={{ formatter: (v) => `${(v as number).toFixed(1)}s` }}
/>
<div className="ts-duration-marks">
<span>0.3s</span>
<span>1.0s</span>
<span>2.0s</span>
</div>
</div>
{/* ── 转场类型卡片网格 ── */}
<div className="ts-grid">
{TRANSITION_OPTIONS.map((opt) => {
const isActive = config.type === opt.value
return (
<div
key={opt.value}
className={`ts-card${isActive ? " active" : ""}`}
onClick={() => handleSelectType(opt.value)}
>
<div className="ts-card-icon">{opt.icon}</div>
<div className="ts-card-name">{opt.label}</div>
{isActive && <span className="ts-card-check">✓</span>}
</div>
)
})}
</div>
{/* ── 底部操作 ── */}
<div className="ts-footer">
<button className="ts-reset-btn" onClick={handleReset}>
重置为无转场
</button>
<div className="ts-current">
当前:
{TRANSITION_OPTIONS.find((o) => o.value === config.type)?.label ?? "无转场"}
{" · "}
{config.duration.toFixed(1)}s
</div>
</div>
</Drawer>
)
}
export default TransitionSelector