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
116 lines
3.3 KiB
TypeScript
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
|