9a51cad137
CI/CD Pipeline / Frontend Lint (push) Successful in 48s
CI/CD Pipeline / Validate - Code Quality (push) Failing after 2m24s
CI/CD Pipeline / Validate - Migration (alembic) (push) Successful in 2m25s
CI/CD Pipeline / Validate - Type Check (mypy) (push) Successful in 2m27s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 3m8s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 3m16s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 1m20s
CI/CD Pipeline / Integration Tests (push) Successful in 3m53s
CI/CD Pipeline / Unit Tests (push) Failing after 7m53s
CI/CD Pipeline / Build Staging API Image (push) Successful in 11m29s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m13s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 26s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 1m3s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m15s
CI/CD Pipeline / Production Browser E2E (push) Failing after 1294h4m36s
CI/CD Pipeline / Build Production Worker Image (push) Failing after 1294h5m22s
CI/CD Pipeline / Build Production Web Image (push) Failing after 1294h5m22s
CI/CD Pipeline / PR Build Worker Image (push) Failing after 1294h7m45s
CI/CD Pipeline / PR Build Web Image (push) Failing after 1294h7m47s
CI/CD Pipeline / PR Build API Image (push) Failing after 1294h7m47s
CI/CD Pipeline / Check if frontend-only change (push) Failing after 1294h7m49s
CI/CD Pipeline / Deploy Production (push) Failing after 1294h37m5s
CI/CD Pipeline / Build Production API Image (push) Failing after 1294h37m51s
87 lines
2.7 KiB
TypeScript
87 lines
2.7 KiB
TypeScript
/**
|
|
* Step 1 模板选择组件
|
|
*/
|
|
import React from "react"
|
|
import type { EditingTemplate } from "@/api/editing-planner"
|
|
import { MODE_GRADIENTS } from "../constants"
|
|
import { useStep1Template } from "../hooks/useStep1Template"
|
|
|
|
interface Step1TemplateSelectProps {
|
|
templates: EditingTemplate[]
|
|
selectedTemplate: string
|
|
onSelectTemplate: (id: string) => void
|
|
}
|
|
|
|
const Step1TemplateSelect: React.FC<Step1TemplateSelectProps> = (props) => {
|
|
const { templates, selectedTemplate, handleSelect, handleKeySelect } = useStep1Template(props)
|
|
|
|
return (
|
|
<div className="xx-form-section">
|
|
<h3>🎨 选择模板</h3>
|
|
{templates.length === 0 ? (
|
|
<div className="xx-empty-state">
|
|
<p>暂无可用模板</p>
|
|
<p style={{ fontSize: 13, color: "var(--text-tertiary)" }}>
|
|
请先在「模板编辑器」中创建模板
|
|
</p>
|
|
</div>
|
|
) : (
|
|
<div className="xx-choice-list">
|
|
{templates.map((tpl) => (
|
|
<div
|
|
key={tpl.id}
|
|
className={`xx-choice-item ${selectedTemplate === tpl.id ? "selected" : ""}`}
|
|
onClick={() => handleSelect(tpl.id)}
|
|
role="button"
|
|
tabIndex={0}
|
|
aria-pressed={selectedTemplate === tpl.id}
|
|
onKeyDown={(e) => handleKeySelect(e, tpl.id)}
|
|
>
|
|
<span className="xx-choice-check">✓</span>
|
|
<div
|
|
className="xx-choice-thumb"
|
|
style={{
|
|
background: MODE_GRADIENTS[tpl.mode] || MODE_GRADIENTS.pip,
|
|
}}
|
|
>
|
|
🎬
|
|
</div>
|
|
<h4>{tpl.name}</h4>
|
|
<p>
|
|
{tpl.estimated_duration}s · {tpl.segments.length}片段
|
|
</p>
|
|
{tpl.tags.length > 0 && (
|
|
<div
|
|
style={{
|
|
display: "flex",
|
|
gap: 4,
|
|
flexWrap: "wrap",
|
|
marginTop: 4,
|
|
}}
|
|
>
|
|
{tpl.tags.map((tag) => (
|
|
<span
|
|
key={tag}
|
|
style={{
|
|
fontSize: 11,
|
|
padding: "1px 6px",
|
|
borderRadius: 6,
|
|
background: "var(--bg-secondary)",
|
|
color: "var(--text-secondary)",
|
|
}}
|
|
>
|
|
{tag}
|
|
</span>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default Step1TemplateSelect
|