Files
xiaoxia-saas/apps/web/src/pages/generate/components/Step2MaterialSelect.tsx
T
xiaoxia ab40c57e9e
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 51s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m16s
CI/CD Pipeline / Validate - Type Check (mypy) (push) Successful in 1m57s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m55s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 2m43s
CI/CD Pipeline / Validate - Migration (alembic) (push) Successful in 2m50s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 38s
CI/CD Pipeline / Build Staging API Image (push) Successful in 3m48s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 30s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m15s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m49s
CI/CD Pipeline / Validate - Code Quality (push) Successful in 7m32s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 7m47s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 6m0s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 8m5s
AI Code Review / AI Code Review (pull_request) Successful in 8m21s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m3s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m13s
CI/CD Pipeline / Integration Tests (push) Successful in 3m11s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 3m20s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 3m33s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m39s
CI/CD Pipeline / Unit Tests (push) Successful in 12m25s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 12m2s
CI/CD Pipeline / CI Gate (pull_request) Successful in 9s
CI/CD Pipeline / Production Browser E2E (pull_request) Failing after 574h45m24s
CI/CD Pipeline / Build Production Worker Image (pull_request) Failing after 574h45m26s
CI/CD Pipeline / Build Production Web Image (pull_request) Failing after 574h45m26s
CI/CD Pipeline / Canary Release to Production (pull_request) Failing after 574h45m24s
CI/CD Pipeline / Production Browser E2E (push) Failing after 574h45m46s
CI/CD Pipeline / Deploy Production (push) Failing after 574h45m48s
CI/CD Pipeline / Build Production API Image (pull_request) Failing after 574h45m26s
CI/CD Pipeline / CI Gate (push) Failing after 574h45m49s
CI/CD Pipeline / Build Production API Image (push) Failing after 574h45m50s
CI/CD Pipeline / Build Production Worker Image (push) Failing after 574h45m50s
CI/CD Pipeline / ACR Image Cleanup (pull_request) Failing after 574h56m19s
CI/CD Pipeline / Staging E2E Tests (pull_request) Failing after 574h56m23s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Failing after 574h56m25s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Failing after 574h57m15s
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 574h57m17s
CI/CD Pipeline / PR Build Worker Image (push) Failing after 574h57m19s
CI/CD Pipeline / PR Build API Image (push) Failing after 574h57m23s
CI/CD Pipeline / Frontend Lint (push) Failing after 574h58m17s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Failing after 574h58m51s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Failing after 574h58m53s
CI/CD Pipeline / Check if frontend-only change (push) Failing after 575h0m14s
CI/CD Pipeline / Build Staging Web Image (pull_request) Failing after 574h58m55s
CI/CD Pipeline / Build Staging API Image (pull_request) Failing after 574h58m57s
CI/CD Pipeline / Deploy Production (pull_request) Failing after 575h19m14s
CI/CD Pipeline / Canary Release to Production (push) Failing after 575h19m38s
CI/CD Pipeline / Build Production Web Image (push) Failing after 575h19m40s
CI/CD Pipeline / Staging API Integration Tests (pull_request) Failing after 575h30m11s
CI/CD Pipeline / PR Build Web Image (pull_request) Failing after 575h30m25s
CI/CD Pipeline / PR Build Web Image (push) Failing after 575h31m11s
feat: sync selected materials to edit_plan_clips on Step2 (PR #1469)
- New API updateEditPlanClips (PUT /templates/{id}/editor/clips)
- useStep2Materials: debounced 800ms clips write, same duration
  logic as FrontendPreviewPlayer.buildPlaybackSegments
- buildClipsFromAssets shared util ensures preview/DB consistency
- Supports manual + smart-match modes, silent failure
2026-08-23 16:25:50 +08:00

99 lines
3.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Step 2 素材选择组件
*/
import React from "react"
import type { TemplateSegment } from "@/api/templates/types"
import { useStep2Materials } from "../hooks/useStep2Materials"
import MaterialModeTabs from "./material/MaterialModeTabs"
import ManualMaterialList from "./material/ManualMaterialList"
import SmartMatchInput from "./material/SmartMatchInput"
import SmartMatchResults from "./material/SmartMatchResults"
interface Step2MaterialSelectProps {
materialMode: "manual" | "auto"
onMaterialModeChange: (mode: "manual" | "auto") => void
selectedMaterials: string[]
onSelectedMaterialsChange: (ids: string[]) => void
smartSelectedIds: string[]
onSmartSelectedIdsChange: (ids: string[]) => void
/** 当前选中的模板/草稿 ID,用于自动保存 */
selectedTemplate?: string
/** 当前模板的 segments(用于构建 clips duration) */
templateSegments?: TemplateSegment[]
}
const Step2MaterialSelect: React.FC<Step2MaterialSelectProps> = (props) => {
const m = useStep2Materials(props)
return (
<div className="xx-form-section">
<h3>📦 选择素材</h3>
<MaterialModeTabs mode={m.materialMode} onModeChange={m.onMaterialModeChange} />
<div className="xx-form-field" style={{ marginTop: 12 }}>
<label>选择视频库</label>
<select
value={m.selectedLibraryId}
onChange={(e) => m.setSelectedLibraryId(e.target.value)}
>
{m.libraries.map((lib) => (
<option key={lib.id} value={lib.id}>
{lib.name}
</option>
))}
</select>
</div>
{m.materialMode === "manual" && (
<>
<div
style={{
marginTop: 14,
display: "flex",
alignItems: "center",
gap: 10,
}}
>
<span className="xx-pill xx-pill-ok">已选 {m.selectedMaterials.length} 个素材</span>
</div>
<ManualMaterialList
materials={m.materials}
materialsLoading={m.materialsLoading}
selectedMaterials={m.selectedMaterials}
onToggle={m.handleToggleMaterial}
/>
</>
)}
{m.materialMode === "auto" && (
<div className="xx-smart-match-section">
<SmartMatchInput
matching={m.smartMatching}
onMatch={m.handleSmartMatch}
hasMatched={m.hasMatched}
onRefresh={m.handleRefreshMatch}
materialsCount={m.materials.items.length}
loading={m.materialsLoading}
/>
<SmartMatchResults
matchedAssets={m.smartMatchedResults}
selectedIds={m.smartSelectedIds}
matching={m.smartMatching}
hasMatched={m.hasMatched}
onToggle={m.handleToggleSmartSelect}
onSelectAll={m.handleSelectAllMatched}
onClear={m.handleClearSmartSelect}
formatDuration={m.formatDuration}
selectedTotalDuration={m.smartSelectedTotalDuration}
/>
</div>
)}
</div>
)
}
export default Step2MaterialSelect